tech talk #2: bash and the operator “=~”

in #linux4 years ago

a couple of years ago i got an assignment: transforming some perl programs into shell scripts. what was supposed to be a simple script became a monster with more than 1000 lines in total.

shell scripts are meant to work like wrappers, not like programs. anyway… with that assignment i ended up discovering the beauty of built-ins (maybe a topic for the next tech talk), and the operator =~. if your’re familiar with perl, then this is not new. however, if it’s not the case, komm mit mir, mein Freund!

when we match strings in shell, it’s quite common to use grep or expr for such tests. for a quick test, there shouldn’t be any problem at all, given the subshell that will be open won’t affect the performance of the (small) test/script nor disturb the OS.

however, when you’re every now and then making such comparisons, it would be nice to change the approach in favor of the built-ins. (if you make a more advanced use of sed, you will get the idea right away and maybe will stop using it as well.)

here’s goes the thing. instead of:

$ cat /etc/passwd | \ while read line; do if [[ $(echo $line | grep -E '^[[:alnum:]]{1,4}:') ]]; then echo match found - line: $line fi done

we should write:

$ cat /etc/passwd | \ while read line; do if [[ $line =~ ^[[:alnum:]]{1,4}: ]]; then echo match found - line: $line fi done

sounds way cooler, huh? obviously i’m aware of the useless use of cat, but this is just for the sake of an example. for this isolated case, it’d be better to run grep directly on the /etc/passwd file.

$ grep -E '^[[:alnum:]]{1,4}:' /etc/passwd

another nice built-in is the string replacement (i would have saved this for another tech talk, but here we go!):

$ f=foo $ echo ${f/oo/ubar} fubar

there is also the possibility of repeating the replacement:

$ f=foo $ echo ${f//oo/ubar} fubarubar

there are other built-ins for strings expansions/substitutions. it is worth checking the bash’s manpage for more info. :)