将部分匹配模式保存到变量

Ben*_*ijl 12 regex variables bash extraction

我想提取一个匹配模式的子字符串并将其保存到文件中.示例字符串:

Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我想在括号之间提取部分[sdf].

我试图grep -e '[$subtext]'将括号中的文本保存到变量.当然它不起作用,但我正在寻找类似于此的方法.在这样的正则表达式中包含变量会非常优雅.我能做什么最好的?

谢谢!

Cha*_*ffy 12

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
Run Code Online (Sandbox Code Playgroud)

如果你想把它放在一个循环中,你可以这样做; 这是一个例子:

while read -r line; do
  if [[ $line =~ \[([^]]+)\] ]] ; then
    drive="${BASH_REMATCH[1]}"
    do_something_with "$drive"
  fi
done < <(dmesg | egrep '\[([hsv]d[^]]+)\]')
Run Code Online (Sandbox Code Playgroud)

这种方法没有外部调用进入循环 - 所以shell不需要forkexec启动外部程序,如sedgrep.因此,它可以说比这里提供的其他方法更清洁.

顺便说一句,你最初的方法(使用grep)并不是那么遥远; using grep -o将仅输出匹配的子字符串:

$ subtext=$(egrep -o "\[[^]]*\]" <<<"$line")
Run Code Online (Sandbox Code Playgroud)

...虽然这包括捕获内的括号,因此不是100%正确.


Ste*_*hen 10

可能有更好的方法只使用bash,但是:

echo 'Apr 12 19:24:17 PC_NMG kernel: sd 11:0:0:0: [sdf] Attached SCSI removable disk' \
| sed -s 's/.*\[\(.*\)\].*/\1/'
Run Code Online (Sandbox Code Playgroud)

正如约根所指出的,这与不匹配的线匹配.如果您不想输出不匹配的行,请使用'-n'以使其不输出模式,并使用'/ p'在匹配时输出模式.

| sed -n 's/.*\[\(.*\)\].*/\1/p'
Run Code Online (Sandbox Code Playgroud)