【发布时间】:2012-04-29 23:12:44
【问题描述】:
我有一个包含多列数据的大型文本文件。我正在尝试编写一个脚本,该脚本从命令行接受列号和关键字,并在显示任何匹配项的整行之前搜索任何匹配项。
我一直在尝试以下方式:
grep $fileName | awk '{if ($'$columnNumber' == '$searchTerm') print $0;}'
但这根本不起作用。我在正确的路线上吗?谢谢你的帮助!
【问题讨论】:
我有一个包含多列数据的大型文本文件。我正在尝试编写一个脚本,该脚本从命令行接受列号和关键字,并在显示任何匹配项的整行之前搜索任何匹配项。
我一直在尝试以下方式:
grep $fileName | awk '{if ($'$columnNumber' == '$searchTerm') print $0;}'
但这根本不起作用。我在正确的路线上吗?谢谢你的帮助!
【问题讨论】:
-v 选项可用于将 shell 变量传递给awk 命令。
您可能正在寻找以下内容:
awk -v s=$SEARCH -v c=$COLUMN '$c == s { print $0 }' file.txt
编辑:
我一直在尝试编写更优雅、更紧凑的代码。所以这就是丹尼斯的意思:
awk -v s="$search" -v c="$column" '$c == s { print $0 }' file.txt
【讨论】:
COLUMNS(复数)是一个环境变量,与您的 COLUMN 变量的名称非常相似。我建议您习惯性地使用小写或混合大小写的变量名称,以减少名称冲突的机会。
看起来很合理。尝试使用set -x 来查看传递给awk 的确切内容。您还可以使用不同的和/或更多的 awk 东西,包括摆脱单独的 grep:
awk -v colnum=$columnNumber -v require="$searchTerm"
"/$fileName/ { if (\$colnum == require) print }"
通过设置 awk 变量(在本例中为colnum 和require)然后使用文字字符串$colnum 来获取所需的字段,并使用变量require 来获取所需的字符串。
请注意,在所有情况下(使用或不使用grep 命令),$fileName 中的任何正则表达式元字符都将是 meta-y,例如,this.that 将匹配名为 this.that 的文件,但也名为thisXthat的文件。
【讨论】:
-v 变量传递和嵌入式shell 变量。我建议您只使用变量传递,对外部集合使用单引号并避免分散注意力的转义。当您使用-v 时,您还应该引用all shell 变量。匹配变量时,您需要使用匹配运算符而不是斜杠。这是您答案的修订版:awk -v colnum="$columnNumber" -v require="$searchTerm" -v file="$fileName" '$0 ~ file && $colnum == require'。请注意,print 是隐含的。
$ awk '$0 ~ "pattern"' 给出:awk: syntax error near line 1。如果您不必处理古老的 awk,请使用全变量版本。