Home > Back-end >  Bash script with regex and capturing group
Bash script with regex and capturing group

Time:08-21

I'm working on a bash script to rename automatically files on my Synology NAS.

I have a loop for the statement of the files and everything is ok until I want to make my script more efficient with regex.

I have several bits of code which are working like as expected:

filename="${filename//[-_.,\']/ }"
filename="${filename//[éèēěëê]/e}"

But I have this:

filename="${filename//t0/0}"
filename="${filename//t1/1}"
filename="${filename//t2/2}"
filename="${filename//t3/3}"
filename="${filename//t4/4}"
filename="${filename//t5/5}"
filename="${filename//t6/6}"
filename="${filename//t7/7}"
filename="${filename//t8/8}"
filename="${filename//t9/9}"

And, I would like to use captured group to have something like this:

filename="${filename//t([0-9]{1,2})/\1}"
filename="${filename//t([0-9]{1,2})/${BASH_REMATCH[1]}}"

I've been looking for a working syntax without success...

CodePudding user response:

The shell's parameter expansion facility does not support regular expressions. But you can approximate it with something like

filename=$(sed 's/t\([0-9]\)/\1/g' <<<"$filename")

This will work regardless of whether the first digit is followed by additional digits or not, so dropping that requirement simplifies the code.

CodePudding user response:

If you want the last or all t[0-9]{1,2}s replaced:

$ filename='abt1cdt2eft3gh'; [[ "$filename" =~ (.*)t([0-9]{1,2}.*) ]] && filename="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"; echo "$filename"
abt1cdt2ef3gh

$ filename='abt1cdt2eft3gh'; while [[ "$filename" =~ (.*)t([0-9]{1,2}.*) ]]; do filename="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"; done; echo "$filename"
ab1cd2ef3gh

Note that the "replace all" case above would keep iterating until all t[0-9]{1,2}s are changed, even ones that didn't exist in the original input but were being created by the loop, e.g.:

$ filename='abtt123de'; while [[ "$filename" =~ (.*)t([0-9]{1,2}.*) ]]; do filename="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"; echo "$filename"; done
abt123de
ab123de

whereas the sed script in @tripleee's answer would not do that:

$ filename='abtt123de'; filename=$(sed 's/t\([0-9]\)/\1/g' <<<"$filename"); echo "$filename"
abt123de
  • Related