我正在尝试编写一个脚本,通过将起始列、增量值和文件名作为运行时参数来打印文件的每 N 列。下面是我的脚本:
file=$1
st=$2
inc=$3
echo $file
echo $st
echo $inc
awk '{for (i = $st; i <= NF; i += $inc) printf ("%s%c", $i, i + $inc <= NF ? " " : "\n");}' $file
我无法得到结果。有人可以帮助我吗?我的输入可以是这样的script.sh file_name 1 4
提前致谢。:-)
答案1
Shell 变量不会自动变成awk
变量(在 中awk
,变量也表示为var
,而不是$var
第var
th 个字段)。如果要将 shell 变量传递给awk
,一种简单的方法是使用环境:
#! /bin/sh -
file=$1
ST=$2
INC=$3
export ST INC
awk '
{
sep = ""
for (i = ENVIRON["ST"]; i <= NF; i += ENVIRON["INC"]) {
printf "%c%s", sep, $i
sep = OFS
}
printf "\n"
}' < "$file"
请记住引用您的 shell 变量,并且awk
不能将任意文件名作为参数(因为它会处理其中一些带有 a=
或-
专门调用的文件名)。
传递变量的另一种方法awk
是在 awk 脚本之后使用-v awkvar="$shellvar"
orawkvar="$shellvar"
参数,但是这些不能用于任意字符串,因为转义序列在其中扩展(例如成为换行符)并且在 GNU \\
4.2\
或更高版本中,\n
awk
以 开头@/
和结尾的值/
会被特殊处理除非在 POSIX 模式下。
awk -v st="$st" -v inc="$inc" '{for (i = st; i <= NF; i += inc)...}' < "$file"
或者
awk '{for (i = st; i <= NF; i += inc)...}' st="$st" inc="$inc" < "$file"
在这里就可以了,因为这些变量仅包含数字(所以没有反斜杠)。
无论你做什么,都不要做:
awk 'for (i = '"$st"'; i <= NF; i += '"$inc"')...'
更不用说
awk 'for (i = '$st'; i <= NF; i += '$inc')...'
也就是说,让 shell 扩展传递给 的代码中的$st
和变量的值,因为这会产生命令注入漏洞(例如,对于like的值)。$inc
awk
st
system("reboot")
答案2
我已经更正了你的脚本,现在它可以工作了。有两个错误。 (a) 您必须手动将 shell 变量传递给 awk(这是使用-v awk_var="$shell_var"
语法完成的),并且 (b) 您不应该使用$
它来表示变量,$
符号仅用于字段位置。
file=$1
st=$2
inc=$3
echo $file
echo $st
echo $inc
awk -v st="$st" -v inc="$inc" '{for (i = st; i <= NF; i += inc) printf ("%s%c", $i, i + inc <= NF ? " " : "\n");}' $file