在 (BSD) UNIX 环境中,我想使用正则表达式捕获特定的子字符串。
假设dmesg
命令输出包含以下行:
pass2: <Marvell Console 1.01> Removable Processor SCSI device
我想捕获<
和>
字符之间的文本,例如
dmesg | <sed command>
应该输出:
Marvell Console 1.01
但是,如果正则表达式不匹配,它不应该输出任何内容。许多解决方案包括sed -e 's/$regex/\1/
如果未找到匹配项将输出整个输入,这不是我想要的。
相应的正则表达式可以是:
regex="^pass2\: \<(.*)\>"
我如何正确使用sed
or进行正则表达式匹配grep
?请注意,该grep -P
选项在我的 BSD UNIX 发行版中不可用。不过,该sed -E
选项是可用的。
答案1
尝试这个,
sed -nE 's/^pass2:.*<(.*)>.*$/\1/p'
或者 POSIXly(-E
截至 2019 年尚未达到 POSIX 标准):
sed -n 's/^pass2:.*<\(.*\)>.*$/\1/p'
输出:
$ printf '%s\n' 'pass2: <Marvell Console 1.01> Removable Processor SCSI device' | sed -nE 's/^pass2:.*<(.*)>.*$/\1/p'
Marvell Console 1.01
这只会打印<...>
每行最后一次出现的情况。
答案2
-o
在 grep 下只打印匹配的部分怎么样?不过,我们仍然需要删除<>
, buttr
在那里工作。
dmesg |egrep -o "<([a-zA-Z\.0-9 ]+)>" |tr -d "<>"
Marvell Console 1.01
答案3
我使用 sed、awk 和 python 尝试了以下 3 种方法
sed命令
echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | sed "s/.*<//g"|sed "s/>.*//g"
输出
Marvell Console 1.01
awk 命令
echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | awk -F "[<>]" '{print $2}'
输出
Marvell Console 1.01
Python
#!/usr/bin/python
import re
h=[]
k=open('l.txt','r')
l=k.readlines()
for i in l:
o=i.split(' ')
for i in o[1:4]:
h.append(i)
print (" ".join(h)).replace('>','').replace('<','')
输出
Marvell Console 1.01
答案4
您可以使用以下grep -o -e
命令提取子字符串:
cat some.log | grep "lineWithThisText" | grep -o -e 'SomeSequence1[0-9]*[A-Z]*SomeSequence2'
由于某种原因,此 grep regex match 命令中的 1 个或多个匹配项*
不起作用。+
使用以下命令阅读 grep 手册:
man grep
阅读有关选项-o
和 的信息-e
。
我在工作中使用它从多个日志行中提取大量数据。