I want to extract a substring matching a pattern and save it to a file. An example string:
Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk
I want to extract the part between the brackets, in this case [sdf]
.
I tried to do something like grep -e '[$subtext]'
to save the text in the brackets to a variable. Of course it doesn't work, but I am looking for a way similar to this. It would be very elegant to include a variable in a regex like this. What can I do best?
Thanks!
BASH_REMATCH
is an array containing groups matched by the shell.
$ line='Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk'
$ [[ $line =~ \[([^]]+)\] ]]; echo "${BASH_REMATCH[1]}"
sdf
If you want to put this in a loop, you can do that; here's an example:
while read -r line; do
if [[ $line =~ \[([^]]+)\] ]] ; then
drive="${BASH_REMATCH[1]}"
do_something_with "$drive"
fi
done < <(dmesg | egrep '\[([hsv]d[^]]+)\]')
This approach puts no external calls into the loop -- so the shell doesn't need to fork
and exec
to start external programs such as sed
or grep
. As such, it is arguably significantly cleaner than other approaches offered here.
BTW, your initial approach (using grep) was not that far off; using grep -o
will output only the matching substring:
$ subtext=$(egrep -o "\[[^]]*\]" <<<"$line")
...though this includes the brackets inside the capture, and thus is not 100% correct.