使用正则表达式从字符串中减去值

时间:2012-02-28 16:19:11

标签: regex awk grep

有一些日志文件。

$> cat ./text
Tue, 28 Feb 2012 15:43:20 407a3f8bbf704e41bef1f4c0ac24f310 FAILED
Tue, 2012 15:45:10 525b13aed6094417a56fd7bc67a10ad7 FAILED
Tue, 28 Feb 2012 15:47:08 ae3e2dc3e5b14d0eb7338ab308a32c8e
Tue, Feb 2012 15:52:26 18486cbede4e4cb4bee931bf29823dda FAILED
Tue, 28 Feb 2012 15:54:17 3c96983a68dd4c5e968dcad512bf77e9 FAILED
Tue, Feb 2012 15:56:30 2191e5260aa44a2a8997c47d710d6fbb FAILED
Tue, 28 Feb 2012 15:58:25 083fc56361414695b4e5cf54f8c57a9e FAILED
28 Feb 2012 16:01:55 5cbad64d2d62429c97ed7fdf98087c44 FAILED
Tue, 28 Feb 2012 16:03:37 a0d33b998b8247ffbecb984198453c0b
28 Feb 2012 16:05:32 cf9c1893e8b64aa89636a8cfeff56cf2 FAILED
Tue, 28 Feb 2012 16:06:53 027d99f7fa68436d9000661a7af07e2a PASSED

使用grep很容易获得所有十六进制值。

$> grep --only-matching --perl-regex "[0-9a-f]{32}" ./text
407a3f8bbf704e41bef1f4c0ac24f310
525b13aed6094417a56fd7bc67a10ad7
ae3e2dc3e5b14d0eb7338ab308a32c8e
18486cbede4e4cb4bee931bf29823dda
3c96983a68dd4c5e968dcad512bf77e9
2191e5260aa44a2a8997c47d710d6fbb
083fc56361414695b4e5cf54f8c57a9e
5cbad64d2d62429c97ed7fdf98087c44
a0d33b998b8247ffbecb984198453c0b
cf9c1893e8b64aa89636a8cfeff56cf2
027d99f7fa68436d9000661a7af07e2a

但是如何使用awk来完成?

所以实际的问题是:我如何减去一些值,匹配一些正则表达式,来回给定一个字符串?例如,在awk的某些行 - 源文件中,我有$ 0值,实际上是整个字符串,如"Tue, Feb 2012 15:56:30 2191e5260aa44a2a8997c47d710d6fbb FAILED"。我正在寻找一些awk命令来获取十六进制值,如:

 hex = command_name( $0, "[0-9a-f]{32}" )

hex将等于2191e5260aa44a2a8997c47d710d6fbb

我该怎么做?

6 个答案:

答案 0 :(得分:1)

你可以使用match()(--re-interval可能需要gawk):

$ gawk --re-interval '{ match($0, /[0-9a-fA-F]{32}/,arr); print arr[0]; }' testdata 
407a3f8bbf704e41bef1f4c0ac24f310
525b13aed6094417a56fd7bc67a10ad7
ae3e2dc3e5b14d0eb7338ab308a32c8e
18486cbede4e4cb4bee931bf29823dda
3c96983a68dd4c5e968dcad512bf77e9
2191e5260aa44a2a8997c47d710d6fbb
083fc56361414695b4e5cf54f8c57a9e
5cbad64d2d62429c97ed7fdf98087c44
a0d33b998b8247ffbecb984198453c0b
cf9c1893e8b64aa89636a8cfeff56cf2
027d99f7fa68436d9000661a7af07e2a

答案 1 :(得分:0)

原始awk程序不支持regex-replace中的反向引用。如果你很幸运并且可以访问GNU awk,你可以使用sub()函数来提取字符串的一部分。理论上它的工作原理如下:

hex = sub(/^.* ([0-9a-fA-F]+) .*$/, "\1");

由于我手边没有GNU awk,你必须四处寻找正确的语法(例如"\1""\\1"+ vs {32,32},等等。)

答案 2 :(得分:0)

也许你可以尝试GNU扩展gensub()

$ awk --re-interval '{print gensub(/^.*([0-9a-f]{32}).*$/,"\\1","")}' text
407a3f8bbf704e41bef1f4c0ac24f310
525b13aed6094417a56fd7bc67a10ad7
ae3e2dc3e5b14d0eb7338ab308a32c8e
18486cbede4e4cb4bee931bf29823dda
3c96983a68dd4c5e968dcad512bf77e9
2191e5260aa44a2a8997c47d710d6fbb
083fc56361414695b4e5cf54f8c57a9e
5cbad64d2d62429c97ed7fdf98087c44
a0d33b998b8247ffbecb984198453c0b
cf9c1893e8b64aa89636a8cfeff56cf2
027d99f7fa68436d9000661a7af07e2a

答案 3 :(得分:0)

非GNU awk回答

awk '
  {
    for (i=NF; i>0; i--)
      if (length($i)==32 && ! match($i,/[^0-9a-fA-F]/)) {
        hexvalue = $i
        break  # if you only expect one per line
      }
    print hexvalue    # or do something else
  }
'

答案 4 :(得分:0)

这可能有用或者你:

awk --re-interval -vRS='[0-9a-fA-F]{32}' 'RT{print RT}' file

答案 5 :(得分:0)

如果您的日志文件的结构与显示的样本一致:

awk '{print $6}' ./text