我正在编写一个 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
Run Code Online (Sandbox Code Playgroud)
期望的输出:
A sentence here:
********************************************************
lines I want
lines I want
lines I want
**********************************************************
Run Code Online (Sandbox Code Playgroud)
如果我在对 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
Run Code Online (Sandbox Code Playgroud)
其中第一个位置变量是输入文件。上面的代码什么都不返回。我最初在没有替换的情况下尝试了它pat2,但收到了警告:
awk: warning: escape sequence `\*' treated as plain `*'
Run Code Online (Sandbox Code Playgroud)
我将不得不运行此命令数千次,并且理想情况下会喜欢一个既干净又高效的解决方案。我不依赖于使用awk。
编辑:
我刚刚注意到,即使我在 awk 中手动输入模式,我仍然收到警告消息。我可能没有正确地将变量传递给 awk。
这里有几个选项:
pat1, pat2 被视为正则表达式:
pat1="A sentence here"
pat2='\*{58}'
export pat1 pat2
awk '$0 ~ ENVIRON["pat1"], $0 ~ ENVIRON["pat2"]'
Run Code Online (Sandbox Code Playgroud)
请注意,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"])'
Run Code Online (Sandbox Code Playgroud)
在这里,index()对于搜索针(变量内容)在任何地方干草堆(当前记录(行)),但你也可以做一个简单的全行比较:
awk '"" $0 == ENVIRON["pat1"], "" $0 == ENVIRON["pat2"]'
Run Code Online (Sandbox Code Playgroud)
(""即使在$0和ENVIRON["patx"]都是数字的情况下也强制进行字符串比较)。
避免使用-v如通过,可能包含反斜杠字符的数据awk做了一些C转义序列(\n,\b,\\...)对他们的处理,你需要逃避反斜杠(与GNU awk4.2或以上,价值与开始@/和结束/也是一个问题)。传递的变量也是如此awk '...code...' awkvar="$shellvar"。使用ENVIRON或ARGV代替。
有关更多详细信息,请参阅相关问题的答案。