regex 如何在awk中匹配变量中给定的模式?

k7fdbhmy  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(127)

我想从管道分离文件中提取一个特定模式存在的子串,因此我使用了下面的命令,

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

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

vc9ivgsu

vc9ivgsu1#

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

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使用动态正则表达式:
"~“或”的右边!“~”运算符不需要是正则表达式常量(即,斜杠之间的字符串)。它可以是任何表达。如果需要,将计算表达式并将其转换为字符串;然后将字符串的内容用作regexp。以这种方式计算的正则表达式称为动态正则表达式或计算正则表达式:

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

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

8ulbf1ek

8ulbf1ek2#

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

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

cyej8jka

cyej8jka3#

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

请注意这会带来代码注入(demonstration (see "Variable within the code"))的风险,但此解决方案适用于@fedorqui的答案福尔斯不足的某些语法。

简单模式(单独)

简单地说:

awk "/$mybashvar/"

会成功的

Range Pattern(单独)

这甚至适用于范围模式,而@fedorqui的解决方案则不行。
假设我想匹配"start #${myid}""end"之间的所有行,我们可以这样做:

awk "/start #${myid}/,/end/"

Awk完整脚本

现在,使用双引号会破坏一些awk功能(例如awk变量,因为它们现在将由shell计算,特别是像$1这样的字段变量),对于复杂的awk脚本使用单引号要安全得多(以防止shell解释任何东西)。但是你仍然可以这样绕过去:

awk '/'"$mypattern"'/ {print $1}'

基本上,您仍然在bash变量周围使用双引号,但在其他地方使用单引号,并将它们连接起来以获得完整的awk脚本。

wfypjpf4

wfypjpf44#

这是一种黑客,但它使事情对我来说更简单一点。

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

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

相关问题