Bash supports regular expressions in comparisons via the =~ operator. But what is rarely used or documented is that you can use the ${BASH_REMATCH[n]} array to access successful matches (back-references to capture groups). So if you use parentheses for grouping () in your regex, you can access the content of that group.
Here is an example where I am parsing date placeholders in a text with an optional offset (e.g. |YYYY.MM.DD|+2 ). Storing the format and offset in separate groups:
1 2 3 4 5 6 7 8 9 10 11 12 13 | while read -r line; do while [[ ${line} =~ \|([YMD\\/\ .-]+)\|(\+*[0-9]*) ]]; do dateformat=${BASH_REMATCH[1]} dateformat=${dateformat/YYYY/%Y} dateformat=${dateformat/MMMM/%B} dateformat=${dateformat/MM/%m} dateformat=${dateformat/DD/%d} offset='now' [[ ! -z ${BASH_REMATCH[2]} ]] && offset="${BASH_REMATCH[2]} days" line=${line/|${BASH_REMATCH[1]}|${BASH_REMATCH[2]}/$(date "+${dateformat}" --date="${offset}")} done echo "${line}" done < input |
1 2 3 4 5 6 7 8 9 10 11 12 | |YYYY.MM.DD| |YYYY.MM.DD|+7 |YYYY-MM-DD| |YYYY-MM-DD|+14 |MMMM YYYY| |YYYY/MM| |MM/YYYY| This is a sentence containing a timestamp (|YYYY.MM.DD|+7) with an offset. This is another sentence containing multiple timstamps between |YYYY.MM.DD| and |YYYY.MM.DD|+7. |
1 2 3 4 5 6 7 8 9 10 11 12 | 2017.09.08 2017.09.15 2017-09-08 2017-09-22 September 2017 2017/09 09/2017 This is a sentence containing a timestamp (2017.09.15) with an offset. This is another sentence containing multiple timstamps between 2017.09.08 and 2017.09.15. |