使用 awk 中的正则表达式打印第一个字段只有四个字符的行?

使用 awk 中的正则表达式打印第一个字段只有四个字符的行?
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 awkinfo 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 字母或数字的字段,但可能包含更多,因此它会匹配Elizabethas John,但不会匹配Tom。您可以编写/^[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]$/将正则表达式锚定在开始和结束处,但是如果您想要的是长度领域的,就这样写。

相关内容