我正在尝试通过多变的从 shell 脚本到表的模式识别子集的参数数量。到目前为止,这是我的尝试:
文件“infile”:
ID,GROUP
1,GROUP2
2,GROUP2
3,GROUP4
4,GROUP4
5,GROUP5
6,GROUP5
7,GROUP23
8,GROUP23
9,GROUP23
文件subset.sh:
#!/bin/sh
rm -f outfile_$week
week = $1
shift
for TOKEN in "$@"
do
echo "adding records for" $TOKEN
awk -F "," -v group = $TOKEN '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile >> outfile_$week
done
我还尝试过 group = "$TOKEN", "group = $TOKEN" ,然后都用单引号。我这样提交:
sh subset.sh 061314 GROUP2 GROUP23
我得到的错误信息非常少
Usage: awk [-F fs][-v Assignment][-f Progfile|Program][Assignment|File] ...
非常感谢任何帮助,谢谢!
编辑:我尝试跑步
awk -F "," -v group ="GROUP1" '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile
无济于事...(与上面相同的错误)有人知道这可能发生的任何原因吗?
答案1
你应该写:
-v group="$TOKEN"
而不是-v group = $TOKEN
,这会导致 中的语法错误awk
。
答案2
听起来像你想要的:
awk -F, '
BEGIN {
for (i = 1; i < ARGC; i++) group[ARGV[i]]
ARGC=0
}
NR >= 2 && $2 in group' "$@" < infile
或者,如果您确实想将参数视为正则表达式来匹配第二列:
awk -F, '
BEGIN {
for (i = 1; i < ARGC; i++) group[ARGV[i]]
ARGC=0
}
NR >= 2 {
for (i in group) if ($2 ~ i) {print; next}
}' "$@" < infile
答案3
您面临的直接问题是等号周围的空格。该选项的参数-v
应该是一个赋值。 awk 看到 的参数-v
,后跟脚本 ( =
),然后是文件名( 的值TOKEN
、您的脚本和您的文件名)。
您在 shell 脚本中犯了类似的错误:week = $1
应该是week="$1"
。
顺便一提,总是在命令替换两边加上双引号。例如,如果TOKEN
is *
,它将被当前目录中的文件列表替换。
awk -v "group=$TOKEN"
不过,这不会设置group
为 的值TOKEN
,因为 awk 将赋值的右侧视为 awk 语法中的文字。例如,如果 的值TOKEN
是 7 个字符的字符串foo\bar
,则 awk 变量group
将设置为 6 个字符的字符串foo␈ar
,其中␈
是退格字符(字节值 8)。
将变量传递给 awk 脚本的直接方法是将其导出到环境中,并通过数组使用它ENVIRON
。
此外,您没有group
在 awk 脚本中的任何地方使用该变量。正则表达式/group/
匹配包含 5 个字符的 string 的任何字符串group
。如果您想检查该字段是否恰好等于 的值group
(例如,如果 的值TOKEN
是GROUP2
则包含的字段GROUP24
将不会匹配),请使用相等运算符==
。
export TOKEN
awk -F "," '{ if (FNR > 2 && $2 == ENVIRON["TOKEN"]){print $0} }' infile >> outfile_$week
这是整个脚本,进一步简化为使用 awk 的条件动作语法(这里省略了动作,因为这print $0
是默认的)并避免每次都打开输出文件:
#!/bin/sh
week="$1"
shift
for TOKEN in "$@"
do
echo "adding records for" $TOKEN
awk -F "," 'FNR > 2 && $2 == ENVIRON["TOKEN"]' infile
done >"outfile_$week"
看斯特凡·查泽拉斯的回答使用 awk 的更高级方法不需要多次处理输入文件。