【问题标题】:Passing variable to awk and using that in a regular expression将变量传递给 awk 并在正则表达式中使用它
【发布时间】:2011-01-14 17:11:21
【问题描述】:

我正在学习 awk,但我无法将变量传递给脚本并将其用作正则表达式搜索模式的一部分。

这个例子是人为的,但显示了我的问题。

我的数据如下:

Eddy        Smith       0600000000  1981-07-16    Los Angeles
Frank       Smith       0611111111  1947-04-29    Chicago           
Victoria    McSmith     0687654321  1982-12-16    Los Angeles
Barbara     Smithy      0633244321  1984-06-24    Boston            
Jane        McSmithy    0612345678  1947-01-15    Chicago               
Grace       Jones       0622222222  1985-10-07    Los Angeles
Bernard     Jones       0647658763  1988-01-01    New York          
George      Jonesy      0623428948  1983-01-01    New York          
Indiana     McJones     0698732298  1952-01-01    Miami             
Philip      McJonesy    0644238523  1954-01-01    Miami

我想要一个可以传递变量的 awk 脚本,然后让 awk 脚本为该变量执行正则表达式。 我现在有了这个脚本,名为“003_search_persons.awk”。

#this awk script looks for a certain name, returns firstName, lastName and City

#print column headers
BEGIN {
    printf "firstName lastName City\n";
}

#look for the name, print firstName, lastName and City
$2 ~ name {
    printf $1 " " $2 " " $5 " " $6;
    printf "\n";
}

我这样调用脚本:

awk -f 003_search_persons.awk name=Smith 003_persons.txt

它返回以下内容,这很好。

firstName lastName City
Eddy Smith Los Angeles
Frank Smith Chicago
Victoria McSmith Los Angeles
Barbara Smithy Boston
Jane McSmithy Chicago

但现在我想查找某个前缀“Mc”。我当然可以对此进行硬编码,但我想要一个灵活的 awk 脚本。我在 003_search_persons_prefix.awk 中写了以下内容。

#this awk script looks for a certain prefix to a name, returns firstName, lastName and City

#print column headers
BEGIN {
    printf "firstName lastName City\n";
}

#look for the prefix, print firstName, lastName and City
/^prefix/{
    printf $1 " " $2 " " $5 " " $6;
    printf "\n";
}

我这样调用脚本:

awk -f 003_search_persons_prefix.awk prefix=Mc 003_persons.txt

但现在它找不到任何记录。

问题在于搜索模式“/^prefix/”。我知道我可以用非正则表达式替换那个搜索模式,就像在第一个脚本中一样,但是假设我想用正则表达式来做,因为我需要前缀真的在 lastName 字段的开头,因为它应该是,作为前缀和所有;-)

我该怎么做?

【问题讨论】:

  • 在通道 5 中的清理:去掉所有空语句(尾随分号),将 printf "\n" 更改为简单地打印 "",并将 printf $1 " " $2 等更改为简单地打印 $1、$2 等。

标签: regex variables awk


【解决方案1】:

你可以试试这个

BEGIN{
 printf "firstName lastName City\n";
 split(ARGV[1], n,"=")
 prefix=n[2]
 pat="^"prefix
}
$0 ~ pat{
    print "found: "$0
}

输出

$ awk -f  test.awk name=Jane file
firstName lastName City
found: Jane        McSmithy    0612345678  1947-01-15    Chicago

查看awk documentation 了解更多信息。 (并从头到尾阅读!)

【讨论】:

  • 谢谢,我马上测试一下。
  • 没有必要进行拆分,因为在 arg 列表中使用 name=Jane 会创建一个名为“name”且值为“Jane”的变量,因此您可以在 FNR= 中说 pat="^"name =1 节。无论如何,最好使用“-v”设置变量,这样您就不必解决未在 BEGIN 部​​分填充的变量。
【解决方案2】:

将您的脚本更改为:

BEGIN {
    print "firstName", "lastName", "City"
    ORS = "\n\n"
}

$0 ~ "^" prefix {
    print $1, $2, $5, $6
}

并将其称为

awk -v prefix="Mc" -f 003_search_persons.awk 003_persons.txt

【讨论】:

    【解决方案3】:

    您应该可以原封不动地使用您的原始脚本 - $2 ~ name 已经在进行正则表达式搜索,因此如果您使用 name=^Mc 调用您的脚本,那么它将返回以“Mc”开头的名称。实际上这不是一个很好的例子,因为 Mc 只出现在名称的开头 - 如果您使用 name=^Smith,那么它将找到 Smiths 而不是 McSmiths。

    【讨论】:

    • 但是我必须传递一个正则表达式(^Smith)作为参数,我个人认为这有点难看。
    【解决方案4】:

    awk 是特别需要的吗?我确信这在 awk 中很有可能,但我不知道,如果你只需要完成工作,那么你可以尝试。但不确定该分隔符到底是什么。

    cut -d " " -f1-2,5 file | egrep '^regex'
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    • 2017-09-11
    • 2018-04-06
    • 2017-10-24
    • 2012-07-14
    • 2010-10-04
    • 2020-06-09
    相关资源
    最近更新 更多