在 awk 中使用带有转义字符的 bash 变量从文件中提取行

在 awk 中使用带有转义字符的 bash 变量从文件中提取行

我正在编写一个 bash 脚本(刚刚学习 bash)来根据两种模式从文件中提取一些行。第一个模式只是一个以冒号结尾的句子。第二个模式重复*N(在本例中为 58)次。

示例文件:

lines I don not want
lines I don not want
lines I don not want

A sentence here:
********************************************************
lines I want
lines I want
lines I want
**********************************************************

lines I don not want
lines I don not want
lines I don not want

期望的输出:

A sentence here:
********************************************************
lines I want
lines I want
lines I want
**********************************************************

如果我在 awk 调用中显式输入A sentence here和58 次,我就可以让脚本正常工作,但为了清洁和可读性,我更愿意执行如下操作:\*

pat1="A sentence here"
pat2=`printf -- '\*%.s' {1..58} ; echo`
pat2=${pat2//\\/\\\\}
awk -v pat1="${pat1}" -v pat2="${pat2}" '/{pat1}/ {p=1}; p; /{pat2}/ {p=0}' $1

其中第一个位置变量是输入文件。上面的代码什么也没返回。我最初在没有替换的情况下尝试了它pat2,但收到了警告:

awk: warning: escape sequence `\*' treated as plain `*'

我将不得不运行此命令数千次,并且理想情况下希望有一个既干净又高效的解决方案。我awk根本不依赖于使用。

编辑:

我刚刚注意到,即使我手动将模式输入 awk,我仍然收到警告消息。我可能没有正确地将变量传递给 awk。

答案1

这里有几个选项:

  • pat1、pat2 被视为正则表达式:

    pat1="A sentence here"
    pat2='\*{58}'
    export pat1 pat2
    awk '$0 ~ ENVIRON["pat1"], $0 ~ ENVIRON["pat2"]'
    

    需要注意的是, 4.0.0之前mawk的版本gawk不支持{}扩展正则表达式运算符。对于旧版本的gawk,您可以传递POSIXLY_CORRECT环境变量以使其识别。

    这里使用该start-condition, end-condition [{action}]方法,但您可以使用p标记方法执行相同的操作。

  • pat1, pat2 被视为固定字符串:

    pat1="A sentence here"
    pat2=$(printf '*%.0s' {1..58})
    export pat1 pat2
    awk 'index($0, ENVIRON["pat1"]), index($0, ENVIRON["pat2"])'
    

    在这里,index()搜索(变量内容)中的任何位置草垛(当前记录(行)),但您也可以进行简单的全行比较:

    awk '"" $0 == ENVIRON["pat1"], "" $0 == ENVIRON["pat2"]'
    

    (即使和都是数字的""情况下,也会强制进行字符串比较)。$0ENVIRON["patx"]

避免使用-v传递可能包含反斜杠字符的数据,就像awk某些 C 转义序列 ( \n, \b, \\...) 处理它们一样,因此您需要转义反斜杠(对于 GNU awk4.2 或更高版本,以 开头@/和结尾的值/也是一个问题)。对于像这样传递的变量也是如此awk '...code...' awkvar="$shellvar"。使用ENVIRONARGV代替。

这个相关问题的答案了解更多详情。

相关内容