您好我正在尝试使用awk命令找到正则表达式后打印5行。我有以下内容:
line_start=$(awk '/regex/{print NR}' file)
let line_end=$line_start+4
awk 'NR==$line_start, NR==$line_end' file
这不会打印任何内容。它没有挂起,只是继续下一行。
我研究了一些类似的问题,并看到人们使用-v选项。我应该在这里使用它,他们的情况是更大的awk脚本。
顺便说一下,我正在使用Kornshell
谢谢!
答案 0 :(得分:9)
您的脚本存在一些问题。直接的问题是在第二次调用awk时,你在脚本周围使用单引号,因此$line_start
和$line_end
是由shell扩展的变量,它们作为脚本的一部分逐字传递给AWK。您可以通过使用双引号来解决此问题。
awk "NR==$line_start, NR==$line_end" file
这仅适用于$line_start
和$line_end
是数字。如果它们是字符串,则无法执行此操作,因为shell变量的值最终会被awk解析为awk代码的一部分,而不是字符串。通常,要将字符串传递给awk脚本,可以使用带有-v
的惯用法来定义与shell变量同名的awk变量(如果您愿意,可以使用不同的名称):
awk -v "line_start=$line_start" -v "line_end=$line_end" 'NR==line_start, NR==line_end' file
您的脚本存在更多问题。
/regex/
匹配多个,则$line_start
将包含一个行号列表。 shell会在let
行上抱怨语法错误。如果你想在匹配后显示5行,请在awk中进行计数。
awk '
/regex/ { show_lines = 5 }
show_lines { print; --show_lines; }
' file
如果您只想显示第一个匹配的块,请在show_lines
达到0后退出。
show_lines { print; --show_lines; if (!show_lines) exit; }
答案 1 :(得分:2)
您可以使用sed:
sed -n '/regex/{N;N;N;N;N;p}' file
或者更改awk解决方案:
line_start=$(awk '/regex/{print NR}' file)
let line_end=$line_start+4
awk "{ if (NR>=$line_start && NR<=$line_end) print; }" file
另一个awk解决方案(s.awk)
:
BEGIN { v = -1}
/regex/ { v = 0 }
v > -1 { v++ }
v > -1 && v < 5 { print }
v == 5 { exit }
使用:
awk -f s.awk file