如何匹配awk中变量中给出的模式?

Posted

技术标签:

【中文标题】如何匹配awk中变量中给出的模式?【英文标题】:How to match a pattern given in a variable in awk? 【发布时间】:2017-01-15 23:50:51 【问题描述】:

我想从管道分隔文件中提取存在特定模式的子字符串,因此我使用了以下命令,

awk -F ":" '/REWARD REQ. SERVER HEADERS/print $1, $2, $3, $4' sample_profile.txt

在这里,'REWARD REQ. SERVER HEADERS' 是要在文件中搜索的模式,并将其前 4 部分打印在冒号分隔的行上。

现在,我想发送 bash 变量作为模式。因此我使用了下面的命令,但它不起作用。

awk -v pat="$pattern" -F ":" '/pat/print $1, $2 , $3, $4  sample_profile.txt

如何在单个awk 命令中使用-v-F

【问题讨论】:

【参考方案1】:

如果你想通过一个变量来提供模式,你需要使用~来匹配它:

awk -v pat="$pattern" '$0 ~ pat'

在您的情况下,问题与-F 无关。

当您希望 pat 成为变量时,问题是使用 /pat/。如果你说/pat/awk 将其理解为文字“pat”,因此它会尝试匹配包含字符串“pat”的那些行。

总的来说,你的代码应该是:

awk -v pat="$pattern" -F ":" '$0~patprint $1, $2, $3, $4 ' file
#                             ^^^^^^

看一个例子:

鉴于此文件:

$ cat file
hello
this is a var
hello bye

让我们查找包含“hello”的行:

$ awk '/hello/' file
hello
hello bye

现在让我们尝试以您的方式查找包含在变量中的“pat”:

$ awk -v pat="hello" '/pat/' file
$                                    # NO MATCHES!

现在让我们使用$0 ~ pat 表达式:

$ awk -v pat="hello" '$0~pat' file
hello                                 # WE MATCH!
hello bye

当然,你可以使用这样的表达式来匹配一个字段,比如awk -v pat="$pattern" '$2 ~ pat' file等等。

来自GNU Awk User's Guide → 3.1 How to Use Regular Expressions:

当正则表达式用斜杠括起来时,例如 /foo/,我们称它为正则表达式常量,就像 5.27 是数字常量而“foo”是字符串常量一样。

还有GNU Awk User's Guide → 3.6 Using Dynamic Regexps:

“~”或“!~”运算符的右侧不必是正则表达式 常量(即斜线之间的字符串)。它可能是任何 表达。表达式被评估并转换为字符串,如果 必要的;然后将字符串的内容用作正则表达式。一种 以这种方式计算的正则表达式称为动态正则表达式或计算 正则表达式:

BEGIN  digits_regexp = "[[:digit:]]+" 
$0 ~ digits_regexp     print 

这会将 digits_regexp 设置为描述一个或多个数字的正则表达式, 并测试输入记录是否与此正则表达式匹配。

【讨论】:

如何将变量与文本常量(如“text$varothertext”)混合为模式? @BlackEye 正常使用即可:awk -v pat="text$vothertext" '$0 ~ pat' file.【参考方案2】:
awk -v pat="$pattern" -F":" '$0 ~ pat  print $1, $2, $3, $4 ' sample_profile.txt

您不能在正则表达式// 表示法中使用变量(无法将其与搜索pat 区分开来);您必须使用~(匹配)运算符指定该变量是一个正则表达式。

【讨论】:

【参考方案3】:

这是一种 hack,但对我来说它让事情变得更简单了。

cmd="awk '/$pattern/'"
eval $cmd

首先将其设为字符串可以让您在 awk 的边界之外对其进行操作

【讨论】:

小心使用eval ...如果你不清理$pattern,你可能会做类似pattern="/';rm -rf /;echo '的事情

以上是关于如何匹配awk中变量中给出的模式?的主要内容,如果未能解决你的问题,请参考以下文章

如何匹配和删除模式中的字符串

一行中的多个awk模式匹配

在 AWK 模式中添加当前日期和时间与通配符匹配

Awk多模式匹配,并将输入文件的输出格式化为列。

awk不分配变量并使用$ 0代替

awk next 和模式匹配