我有一个文本文件,我需要在一个字段中识别某个模式。我正在使用AWK,并尝试使用match()函数。
要求是我需要查看数字串中是否存在以下模式
??????1?
??????3?
??????5?
??????7?
即我只对最后一个数字感兴趣,但是一个数字是1,3,5或7。
我有一个解决方案,看起来像这样;
b = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]1[0-9]")
c = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]3[0-9]")
d = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]5[0-9]")
e = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]7[0-9]")
if (b || c || d || e)
{
print "Found a match" $23
}
我认为虽然我应该能够像这样简洁地编写正则表达式;
b = match($23, "[0-9]{6}1[0-9]")
但这不起作用。
我错过了什么,或者是我的正则表达技巧(哪些不是很好),真的那么糟糕?
感谢您的期待
答案 0 :(得分:3)
正则表达式分隔符为/.../
,而不是"..."
。当你在RE上下文中使用引号时,你要告诉awk存在一个字符串文字中的RE,并且该字符串文字被解析两次,一次是在读取脚本时,然后再一次是在#39 ; s执行使得你的RE规范更加复杂,以适应双重解析。
所以,不要写:
b = match($23, "[0-9]{6}1[0-9]")
写:
b = match($23, /[0-9]{6}1[0-9]/)
代替。
但这不是你的问题。您可能遇到的最大问题是您正在调用不支持RE区间的awk版本,例如{6}
。如果您使用的是旧版本的GNU awk,则可以通过添加--re-interval
标志来启用该功能:
awk --re-interval '...b = match($23, /[0-9]{6}1[0-9]/)...'
但是,或者你是否正在使用一个不支持RE_intervals的awk,最好的办法是获得更新版本的gawk。
最后,您的整个脚本可以简化为:
awk --re-interval '$23 ~ /[0-9]{6}[1357][0-9]/{print "Found a match", $23}'
如果您愿意,可以将[0-9]
更改为[[:digit:]]
以获取区域设置。
直到最近才默认支持RE间隔的原因是旧的awk不支持它们,因此在旧的awk中执行时RE为a{2}b
的脚本会一直在寻找那些5个字符和gawk并不希望旧脚本在gawk而不是旧awk中执行时悄然破坏。一些发布回来的gawk家伙正确决定默认启用RE间隔,以方便后向兼容。
答案 1 :(得分:0)
这是一个awk
解决方案:
awk -v FS="" '$7~/(1|3|5|7)/' file
通过将FS
设置为空,每个角色都成为一个字段。然后我们可以测试#7领域。
正如汤姆所说。
awk -v FS="" '$7~/[1357]/' file