我想提取与模式匹配的子字符串并将其保存到文件中。示例字符串:
Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk
我想提取括号之间的部分,在这种情况下[sdf]
。
我试图做一些事情,比如grep -e '[$subtext]'
将括号中的文本保存到变量中。当然它不起作用,但我正在寻找与此类似的方法。在这样的正则表达式中包含一个变量会非常优雅。我能做什么最好?
谢谢!
我想提取与模式匹配的子字符串并将其保存到文件中。示例字符串:
Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk
我想提取括号之间的部分,在这种情况下[sdf]
。
我试图做一些事情,比如grep -e '[$subtext]'
将括号中的文本保存到变量中。当然它不起作用,但我正在寻找与此类似的方法。在这样的正则表达式中包含一个变量会非常优雅。我能做什么最好?
谢谢!
BASH_REMATCH
是一个包含与 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
如果你想把它放在一个循环中,你可以这样做;这是一个例子:
while read -r line; do
if [[ $line =~ \[([^]]+)\] ]] ; then
drive="${BASH_REMATCH[1]}"
do_something_with "$drive"
fi
done < <(dmesg | egrep '\[([hsv]d[^]]+)\]')
这种方法不会将外部调用放入循环中——因此 shell 不需要fork
并exec
启动外部程序,例如sed
or grep
。因此,它可以说比这里提供的其他方法要干净得多。
顺便说一句,您最初的方法(使用 grep)并没有那么遥远;usinggrep -o
将仅输出匹配的子字符串:
$ subtext=$(egrep -o "\[[^]]*\]" <<<"$line")
...虽然这包括捕获内的括号,因此不是 100% 正确的。
仅使用 bash 可能有更好的方法,但是:
echo 'Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk' \
| sed -s 's/.*\[\(.*\)\].*/\1/'
正如 Jurgen 指出的那样,这匹配不匹配的行。如果您不想输出不匹配的行,请使用“-n”以便它不输出模式,并使用“/p”在匹配时输出模式。
| sed -n 's/.*\[\(.*\)\].*/\1/p'
匹配正则表达式,使用分组替换并且仅在正则表达式匹配时打印:
sed -n "s/.*\[\(.*\)\].*/\1/p"
[]
sed 是贪婪的,因此如果您的数据中有更多对,sed 的答案将丢失一些数据。使用 grep+tr 解决方案,或者您可以使用 awk
$ cat file
[sss]Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk [tag] blah blah
$ awk -F"[" '{for(i=2;i<=NF;i++){if($i~/\]/){sub("].*","",$i)};print $i}}' file
sss
sdf
tag