从这个输入开始:
$ cat file1
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
我可以将第一组数字放在括号中:
$ sed -En 's/[0-9]*:/(&)/ p'
Bus 001 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
但如果我也尝试在该行前面加上 & (匹配的字符串),我什么也得不到:
$ sed -En 's/[0-9]*:/(&)/ ; s/^/(&)/ p' infile
()Bus 001 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
()Bus 002 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
我怎样才能做到这一点?
答案1
&
命令的替换部分中的是s
正则表达式匹配的占位符在同一个s
命令中。
您的第二个替换是s/^/(&)/
,并且由于这将匹配任何行开头的空字符串,因此它将()
在每行的开头插入文字字符串。括号将为空,因为&
被空字符串替换。
如果您想匹配数字的第一个子字符串(带有尾随:
),请将它们放入括号中,并将括号中的数字添加到行的开头,那么您必须让命令s
修改一口气,可能是这样的:
$ sed 's/\(.*Device \)\([0-9]*:\)/(\2)\1(\2)/' file
(001:)Bus 001 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
(001:)Bus 002 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
在这里,我确保匹配并收集两个捕获组中设备编号之前的部分以及编号和冒号。然后,我可以将第二组(在括号中)附加并添加到替换文本中的第一组之前。
我将该行的开头部分与 相匹配,.*Device
因为如果我使用 just .*
,它也会吞噬 前面的数字:
,而第二组将只包含冒号。
或者,使用两次替换,其中第一个替换将数字和冒号放在括号中,第二个替换匹配括号并将其添加到行前面:
$ sed -e 's/[0-9]*:/(&)/' -e 's/\(.*\)\((.*)\)/\2\1\2/' file
(001:)Bus 001 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
(001:)Bus 002 Device (001:) ID 1d6b:0002 Linux Foundation 2.0 root hub
简而言之:该s
命令只能修改字符串中与正则表达式匹配的部分,&
占位符被替换为当前命令中与正则表达式匹配的文本s
。如果您需要复制和/或修改文本中间的某些内容和将其移动到行的开头,然后您必须匹配字符串的所有这些部分,可能将它们捕获到捕获组中。