Sté*_*ane 97 regex unix awk sed gawk
我看到很多关于如何使用sed,awk或gawk进行搜索和替换等操作的示例和手册页.
但在我的情况下,我有一个正则表达式,我想对文本文件运行以提取特定的值.我不想做搜索和替换.这是从bash调用的.我们来举个例子:
正则表达式示例:
.*abc([0-9]+)xyz.*
Run Code Online (Sandbox Code Playgroud)
示例输入文件:
a
b
c
abc12345xyz
a
b
c
Run Code Online (Sandbox Code Playgroud)
听起来很简单,我无法弄清楚如何正确调用sed/awk/gawk.我希望做的是,在我的bash脚本中有:
myvalue=$( sed <...something...> input.txt )
Run Code Online (Sandbox Code Playgroud)
我尝试过的事情包括:
sed -e 's/.*([0-9]).*/\\1/g' example.txt # extracts the entire input file
sed -n 's/.*([0-9]).*/\\1/g' example.txt # extracts nothing
Run Code Online (Sandbox Code Playgroud)
mou*_*iel 42
我的sed(Mac OS X)无法使用+.我尝试了*,我添加了p用于打印匹配的标签:
sed -n 's/^.*abc\([0-9]*\)xyz.*$/\1/p' example.txt
Run Code Online (Sandbox Code Playgroud)
为了匹配至少一个数字字符+,我会使用:
sed -n 's/^.*abc\([0-9][0-9]*\)xyz.*$/\1/p' example.txt
Run Code Online (Sandbox Code Playgroud)
Ili*_*oly 32
您可以使用sed来执行此操作
sed -rn 's/.*abc([0-9]+)xyz.*/\1/gp'
Run Code Online (Sandbox Code Playgroud)
-n 不打印生成的行-r这使得你没有逃脱捕获组的parens ().\1 捕获组匹配/g 全球比赛/p 打印结果我为自己写了一个工具,使这更容易
rip 'abc(\d+)xyz' '$1'
Run Code Online (Sandbox Code Playgroud)
PP.*_*PP. 17
我用它perl来让自己更容易.例如
perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/'
Run Code Online (Sandbox Code Playgroud)
这运行Perl,该-n选项指示Perl一次从STDIN读取一行并执行代码.该-e选项指定要运行的指令.
该指令在读取行上运行正则表达式,如果匹配则打印出第一组bracks($1)的内容.
你可以这样做,最后也会有多个文件名.例如
perl -ne 'print $1 if /.*abc([0-9]+)xyz.*/' example1.txt example2.txt
如果您的版本grep支持它,您可以使用该-o选项仅打印与您的正则表达式匹配的任何行的部分.
如果没有,那么这是sed我能想到的最好的:
sed -e '/[0-9]/!d' -e 's/^[^0-9]*//' -e 's/[^0-9]*$//'
Run Code Online (Sandbox Code Playgroud)
...删除/跳过没有数字,对于其余行,删除所有前导和尾随非数字字符.(我只是猜测你的意图是从包含一行的每一行中提取数字).
这样的问题:
sed -e 's/.*\([0-9]*\).*/&/'
Run Code Online (Sandbox Code Playgroud)
.... 要么
sed -e 's/.*\([0-9]*\).*/\1/'
Run Code Online (Sandbox Code Playgroud)
...... sed只支持"贪婪"匹配...所以第一个.*将与该行的其余部分匹配.除非我们可以使用否定的字符类来实现非贪婪的匹配...或者sed与其正则表达式兼容或其他扩展的版本,我们无法从模式空间中提取精确的模式匹配(一行).
您可以使用awkwithmatch()来访问捕获的组:
$ awk 'match($0, /abc([0-9]+)xyz/, matches) {print matches[1]}' file
12345
Run Code Online (Sandbox Code Playgroud)
这试图匹配模式abc[0-9]+xyz。如果这样做,它将把它的切片存储在数组中matches,数组的第一项是块[0-9]+。由于match() 返回该子字符串开始位置的字符位置或索引(1,如果它从字符串的开头开始),因此它会触发该print操作。
您可以使用grep后视和前视:
$ grep -oP '(?<=abc)[0-9]+(?=xyz)' file
12345
$ grep -oP 'abc\K[0-9]+(?=xyz)' file
12345
Run Code Online (Sandbox Code Playgroud)
[0-9]+当模式出现在abc和中时,这会检查模式xyz并仅打印数字。