在AWK命令中将变量传递给NR不起作用

use*_*103 4 unix shell awk ksh

嗨我正在尝试使用awk命令找到正则表达式后打印5行.我有以下内容:

line_start=$(awk '/regex/{print NR}' file)
let line_end=$line_start+4
awk 'NR==$line_start, NR==$line_end' file
Run Code Online (Sandbox Code Playgroud)

这不会打印任何东西.它没有挂起,只是继续下一行.

我研究了一些类似的问题,并看到人们使用-v选项.我应该在这里使用它,他们的情况是更大的awk脚本.

顺便说一下,我正在使用Kornshell

谢谢!

Gil*_*il' 10

您的脚本有几个问题.直接的问题是,在第二次调用awk时,你在脚本周围使用单引号,因此$line_start并且$line_end是由shell扩展的变量,它们作为脚本的一部分直接传递给awk.您可以通过使用双引号来解决此问题.

awk "NR==$line_start, NR==$line_end" file
Run Code Online (Sandbox Code Playgroud)

这只是因为$line_start而且$line_end是数字.如果它们是字符串,则无法执行此操作,因为shell变量的值最终会被awk解析为awk代码的一部分,而不是字符串.通常,要将字符串传递给awk脚本,您可以使用idiom -v来定义与shell变量同名的awk变量(如果您愿意,还可以使用不同的名称):

awk -v "line_start=$line_start" -v "line_end=$line_end" 'NR==line_start, NR==line_end' file
Run Code Online (Sandbox Code Playgroud)

您的脚本存在更多问题.

  • 您解析文件两次.如果文件很大,这可能会很慢,如果数据来自管道而不是磁盘文件,则不可能.
  • 如果有多个匹配/regex/,$line_start则将包含行号列表.shell会抱怨该let行语法错误.

如果你想在匹配后显示5行,请在awk中进行计数.

awk '
  /regex/ { show_lines = 5 }
  show_lines { print; --show_lines; }
' file
Run Code Online (Sandbox Code Playgroud)

如果您只想显示第一个匹配的块,则退出一次show_lines达到0.

  show_lines { print; --show_lines; if (!show_lines) exit; }
Run Code Online (Sandbox Code Playgroud)