![使用 awk 中的正则表达式打印第一个字段只有四个字符的行?](https://linux22.com/image/27383/%E4%BD%BF%E7%94%A8%20awk%20%E4%B8%AD%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%89%93%E5%8D%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AD%97%E6%AE%B5%E5%8F%AA%E6%9C%89%E5%9B%9B%E4%B8%AA%E5%AD%97%E7%AC%A6%E7%9A%84%E8%A1%8C%EF%BC%9F.png)
John Goldenrod:(916) 348-4278:250:100:175
Chet Main:(510) 548-5258:50:95:135
Tom Savage:(408) 926-3456:250:168:200
Elizabeth Stachelin:(916) 440-1763:175:75:300
输出应包含仅包含四个字符的名称的行(john,chet):
awk '$1 ~ /[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]" "/ {print}' file
这似乎对我不起作用。我可以在不使用任何 awk 函数的情况下做到这一点吗?
答案1
awk 中的字段默认由“ ”分隔,这意味着
$1
不包含空格,因此正确的正则表达式$1
是:
awk '$1 ~ /^[a-zA-Z0-9]{4}$/ {print}' file
如果你想保留原来的方法,你也可以使用$0
,即:
awk '$0 ~ /^[a-zA-Z0-9]{4}\s/ {print}' file
为了简化事情,您还可以使用\w
而不是显式定义单词字符,即:
awk '$0 ~ /^\w{4}\s/ {print}' file
如果您只想匹配空格而不是其他内容,TAB
则只需替换\s
为“ ”(不带引号)。
您原来的方法的另一个问题是缺少锚点。由于您没有指定,您的模式^
也$
不能出现在任何地方,即模式将Elizabeth Stachelin
与 with匹配beth
。
答案2
在 AWK 中,您可以使用正则表达式作为图案就像您在 AWK 脚本中经常看到的BEGIN
那样。END
简化的代码可以是这样的
awk '/^[[:alnum:]]{4}\>/'
这就是满足您的需求所需的一切。您不需要行动,{print}
是模式匹配时的默认操作,它打印整个记录,即整行。
[:alnum:]
是基本上的同义词[a-zA-Z0-9]
,具体取决于区域设置。您还可以使用\w
— 只是它还包含下划线_
,它是以下划线的简写[[:alnum:]_]
:
awk '/^\w{4}\>/'
\>
匹配单词的结尾。通过使用它,John:(###)...
如果您有不包含全名的记录,您可以正确匹配字符串。
虽然你问的是 AWK,但我建议使用sed
,在这种情况下它的运行速度几乎是 AWK 的两倍:
sed -n '/^[[:alnum:]]\{4\}\b/p'
\b
是\>
或\<
在 AWK 中。我在 500K 行上进行了测试,匹配了 100K 行,AWK 花费了大约 1.7 秒,sed 仅花费了 0.9 秒。但测试用例是极端的,这只是一个挑剔的建议。
我还建议您阅读man 7 regex
以及man awk
和info awk
。
答案3
第一个字段是$1
,其长度是length($1)
,所以:
awk 'length($1) == 4 {print}'
或者更简洁地说
awk 'length($1) == 4'
您写的内容不起作用有两个原因。首先,您" "
的正则表达式中有一个额外的内容,因此您要求字段包含双引号、空格、双引号。如果解决这个问题,您会得到/[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]/
,它匹配至少包含四个 ASCII 字母或数字的字段,但可能包含更多,因此它会匹配Elizabeth
as John
,但不会匹配Tom
。您可以编写/^[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]$/
将正则表达式锚定在开始和结束处,但是如果您想要的是长度领域的,就这样写。