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.
|