这可能是一个常见/简单的任务,但我无法从网络上的示例或 awk/sed/grep 手册中弄清楚。
所以,这是这样的场景:
- 有一个内部命令行工具,可以为输入文件中的每一行打印出多行结果。
- 我有一个 500K 行的输入文件。
- 在该工具的输出中,总是有一行类似于“src:/some/directory”
- 当且仅当同一输出中存在特定字符串“foo”时,我想提取这一行。
这些行之间的行数可能不同,所以这个问题有些相关,但不完全是我想要做的。 使用 awk 匹配单个文件中的多个正则表达式
如何使用 awk、sed 或 grep 执行此操作?我可以使用 Python 来完成此操作,但我不想这样做,因为我想学习 awk/sed,这可能是一个很好的例子。
这是我用 grep 尝试过的:
tool -inputfile | if grep "foo"; then grep "src: " ; fi > result.txt
这不会产生我预期的结果,可能是因为与缓冲相关的原因。
尝试使用 awk:
tool -inputfile | awk '{for (i=1;i<NF;i++) {if(match($i, "foo")) print ??? }}' > result.txt
如何打印此脚本中包含“src:”的行?
该工具的输出示例:
输出1:
src: /usr/bin
param1: value1 value2
param2: "foo"
param3: "bar" "spam"
param4: "eggs" "spam" "spam"
输出2:
src: /dev/null
param1: value1 value2
param2: "ham" "spam" "eggs"
因此,对于这两种情况,我尝试仅提取第一种情况,即: src: /usr/bin
答案1
如果您知道它src:
出现在行的开头,并且foo
用引号括起来,前面有一个空格,并且该行前面必须有一个冒号,请使用
awk 'BEGIN{a=0} /^$/{if(a==1) print b; a=0} /:.* "foo"/{a=1} /^src:/{b=$0} END{if(a==1) print b}'
我们使用变量a
来记住模式是否foo
出现在输入块中,并使用变量b
来存储src:
行。一开始,a
被设置为 0。每当我们发现空行(即^$
)时,我们就会检查 的值a
,有条件地打印b
并重置a
。如果我们在行"foo"
的前面遇到前面有一个冒号,我们设置a
为 1。如果我们在行src:
的开头遇到 ( ^
),我们将其存储在 中b
。最后,我们再次检查是否a == 1
,如果是,则打印b
。
答案2
简单的 awk
awk '/src/{a=$0}/foo/{b=1}b&&a{print a;exit}'
如果src
或foo
可以在其他地方以不同的格式或其他方式
awk '/^src/{a=$0}/"foo"/{b=1}b&&a{print a;exit}'
如果 foo 总是在后面src
awk '/^src/{a=$0}/"foo"/{print a;exit}'
如果一个文件中有多个 src 块,并且您想要打印每个包含 foo 的块
awk '/^src/{a=$0;b=0}/"foo"/{b=1}b&&a{print a;a=0}'