如何使用awk打印匹配的正则表达式?

mar*_*rix 94 regex awk

使用awk,我需要在文件中找到与正则表达式匹配的单词.

只是想打印与模式匹配的单词.

所以,如果在线,我有:

xxx yyy zzz
Run Code Online (Sandbox Code Playgroud)

和模式:

/yyy/
Run Code Online (Sandbox Code Playgroud)

我想只得到:

yyy
Run Code Online (Sandbox Code Playgroud)

编辑:感谢kurumi我设法写这样的东西:

awk '{
        for(i=1; i<=NF; i++) {
                tmp=match($i, /[0-9]..?.?[^A-Za-z0-9]/)
                if(tmp) {
                        print $i
                }
        }
}' $1
Run Code Online (Sandbox Code Playgroud)

这就是我需要的:)非常感谢!

kur*_*umi 134

这是非常基本的

awk '/pattern/{ print $0 }' file
Run Code Online (Sandbox Code Playgroud)

要求awk搜索pattern使用//,然后打印出该行,默认情况下称为记录,用$ 0表示.至少阅读文档.

如果您只想打印匹配的单词.

awk '{for(i=1;i<=NF;i++){ if($i=="yyy"){print $i} } }' file
Run Code Online (Sandbox Code Playgroud)

  • 由于`print`是默认动作:`awk'/ pattern /'file`就足够了. (47认同)
  • 我不怀疑你的知识.但是,这些信息可能对其他人找到答案很有用. (17认同)
  • @Johnsyweb,是的,我知道这个事实.对于像marverix这样的初学者来说,它意味着更具视觉效果. (15认同)
  • 它不会是`$ i =="yyy"`; 对于正则表达式,它将是`$ i~/yyy /`. (5认同)
  • 注意:@marverix 需要做更多的功课才能让 `for` 循环工作,如果 (a) "yyy" 是一个正则表达式而不是一个直字符串,并且 (b) 如果 "yyy" 不匹配记录中的整个字段。 (3认同)

Joh*_*web 103

听起来你正试图模仿GNU的grep -o行为.这样做只要你想要每行的第一场比赛:

awk 'match($0, /regex/) {
    print substr($0, RSTART, RLENGTH)
}
' file
Run Code Online (Sandbox Code Playgroud)

这是一个例子:

% awk 'match($0, /a.t/) {
    print substr($0, RSTART, RLENGTH)
}
' /usr/share/dict/words | head
act
act
act
act
aft
ant
apt
art
art
art
Run Code Online (Sandbox Code Playgroud)

阅读match,substr,RSTARTRLENGTHawk手册.

之后,您可能希望扩展它以处理同一行上的多个匹配.我不能为你做所有的功课:-)


小智 30

gawk可以使用此作为动作获取每一行的匹配部分:

{ if (match($0,/your regexp/,m)) print m[0] }
Run Code Online (Sandbox Code Playgroud)

match(string,regexp [,array])如果存在数组,则清除它,然后将数组的第0个元素设置为regexp匹配的字符串的整个部分.如果regexp包含括号,则数组的整数索引元素将设置为包含与相应的带括号的子表达式匹配的字符串部分. http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions


Dan*_*der 10

如果您只对最后一行输入感兴趣并且您希望只找到一个匹配项(例如shell命令汇总行的一部​​分),您还可以尝试这个非常紧凑的代码,从如何打印regexp匹配中采用使用`awk`?:

$ echo "xxx yyy zzz" | awk '{match($0,"yyy",a)}END{print a[0]}'
yyy
Run Code Online (Sandbox Code Playgroud)

或者具有部分结果的更复杂版本:

$ echo "xxx=a yyy=b zzz=c" | awk '{match($0,"yyy=([^ ]+)",a)}END{print a[1]}'
b
Run Code Online (Sandbox Code Playgroud)

警告:awk match()具有三个参数的函数仅存在于gawk,而不是存在于mawk

下面是一个使用另一种很好的解决方案回顾后发正则表达式grep代替awk.此解决方案对您的安装的要求较低:

$ echo "xxx=a yyy=b zzz=c" | grep -Po '(?<=yyy=)[^ ]+'
b
Run Code Online (Sandbox Code Playgroud)

  • @ArthurAccioly 正确。我使用这个术语从 ping 调用中提取平均往返时间,这就是它的来源。有趣的是,花了 4 年才发现它;) (2认同)

Chr*_*nat 10

如果Perl是一个选项,你可以试试这个:

perl -lne 'print $1 if /(regex)/' file
Run Code Online (Sandbox Code Playgroud)

要实现不区分大小写的匹配,请添加i修饰符

perl -lne 'print $1 if /(regex)/i' file
Run Code Online (Sandbox Code Playgroud)

在比赛结束后打印所有内容:

perl -lne 'if ($found){print} else{if (/regex(.*)/){print $1; $found++}}' textfile
Run Code Online (Sandbox Code Playgroud)

在比赛结束后打印比赛和所有内容:

perl -lne 'if ($found){print} else{if (/(regex.*)/){print $1; $found++}}' textfile
Run Code Online (Sandbox Code Playgroud)


小智 5

在这种情况下使用 sed 也可以很优雅。示例(将行替换为行中匹配的组“yyy”):

$ cat testfile
xxx yyy zzz
yyy xxx zzz
$ cat testfile | sed -r 's#^.*(yyy).*$#\1#g'
yyy
yyy
Run Code Online (Sandbox Code Playgroud)

相关手册页:https://www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions


Zeu*_*eus 5

题外话,这也可以使用 grep 来完成,如果有人正在寻找 grep 解决方案,只需将其张贴在这里

echo 'xxx yyy zzze ' | grep -oE 'yyy'
Run Code Online (Sandbox Code Playgroud)