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

问题描述 投票:0回答:4

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

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

这里,“奖励要求”。 SERVER HEADERS' 是要在文件中搜索的模式,并在冒号分隔的行上打印其前 4 部分。

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

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

如何在单个

-v
命令中使用
-F
awk

regex bash shell awk substring
4个回答
104
投票

如果你想通过变量提供模式,你需要使用

~
来匹配它:

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

就您而言,问题与

-F
无关。

问题是当您希望

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

总而言之,您的代码应该是:

awk -v pat="$pattern" -F ":" '$0~pat{print $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 用户指南 → 3.1 如何使用正则表达式:

当正则表达式包含在斜杠中时,例如 /foo/,我们将其称为正则表达式常量,就像 5.27 是一个数字常量,“foo”是一个字符串常量。

GNU Awk 用户指南 → 3.6 使用动态正则表达式:

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

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

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


12
投票
awk -v pat="$pattern" -F":" '$0 ~ pat { print $1, $2, $3, $4 }' sample_profile.txt

您不能在正则表达式

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


0
投票

这是一种黑客攻击,但它让我的事情变得更简单。

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

首先将其设为字符串,这样您就可以超越 awk 的边界来操作它


0
投票

我不太明白为什么没有答案提到最明显的解决方案:使用双引号

只需这样做:

awk "/$mybashvar/"

会起作用的。

这甚至适用于 范围模式,而 @fedorqui 的解决方案则不然。

考虑到我想匹配

"start #${myid}"
"end"
之间的所有行,我们可以这样做:

awk "/start #$myid/,/end/"
© www.soinside.com 2019 - 2024. All rights reserved.