我正在编写一个 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"]'
(即使和都是数字的
""
情况下,也会强制进行字符串比较)。$0
ENVIRON["patx"]
避免使用-v
传递可能包含反斜杠字符的数据,就像awk
某些 C 转义序列 ( \n
, \b
, \\
...) 处理它们一样,因此您需要转义反斜杠(对于 GNU awk
4.2 或更高版本,以 开头@/
和结尾的值/
也是一个问题)。对于像这样传递的变量也是如此awk '...code...' awkvar="$shellvar"
。使用ENVIRON
或ARGV
代替。
看这个相关问题的答案了解更多详情。