当我使用 AWK 查找和替换时,如何显示引号?

当我使用 AWK 查找和替换时,如何显示引号?

目前,我正在使用 AWK 查找并替换字符串前三次出现的部分内容。该字符串的格式如下,文件中有许多这样的字符串:

func(tempID="39849235",count='12');

使用此链接,我找到了一种使用 AWK 查找和替换字符串前三个实例的方法。我将其更改为我需要它执行的操作,我的脚本片段如下:

id=12349876
awk 'BEGIN {matches=0}
     matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ }
     { print $0 }' filName.py >filName.py.changed

上述代码的目的是匹配任何包含 tempID 的行,并将分配给 tempID 的数字替换为变量中保存的值$id。查找和替换工作正常,但我似乎遇到的一个问题是,无论我如何构造它,输出都会打印不带引号的 $id。我尝试过转义引号并添加单个勾号,但无论如何,该行都会更改为:

func(tempID=39849235,count='12');

我尝试删除替换部分周围的双引号并将其构造为tempID="$id",但不幸的是,这只是用字符串替换了 ID 号$id

请告诉我是否有办法找到并替换 tempID 值并用引号括起来。我没有被 AWK 所困扰,所以使用任何其他实用程序(例如 sed)的任何其他方法也可以正常工作。

答案1

在您的命令中,有引号被 shell 解释并删除,有引号被 解释并删除awk,那么您需要保留引号。您应该对它们进行转义:

id=12349876
awk 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ }
 { print $0 }' filName.py >filName.py.changed              # ^^  here ^^

解释。你的原始命令如下

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                      ^^   ^^                            ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^              ^
#     this variable is expanded by the shell and gets to awk as its value            ^^^

这是改进后的命令:

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                        ^^   ^^                              ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^                  ^
#     these quotes will appear in the output thanks to being escaped                ^        ^
#     this variable is expanded by the shell and gets to awk as its value              ^^^

为了减少引用狂潮,您可以使用-v选项将变量传递给awk。然后,您无需在序列中间关闭并重新打开单引号,只需让 shell 扩展$id。相反,未引用的(如awk所见)id会自行扩展awk。我们需要添加的双引号应该像以前一样进行转义:

id=12349876
awk -v id="$id" 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\""id"\""); matches++ }
 { print $0 }' filName.py >filName.py.changed

答案2

为了实现您想要做的事情,您需要:

对于双引号:

  • "AWK:在其他双引号内转义双引号。
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

对于单引号:

  • Shell:退出你的整个 awk 脚本,使用其中'…'的另一组。 =>'…'
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'$LINUX linux-gnu $CPUTYPE

  • Shell:Escape'您想要按字面意思打印。
    'apostrophe that'\''s literal'=>apostrophe that's literal

例如

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'

相关内容