输出输入中的每 N 列

输出输入中的每 N 列

我正在尝试编写一个脚本,通过将起始列、增量值和文件名作为运行时参数来打印文件的每 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,而不是$varvarth 个字段)。如果要将 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\或更高版本中,\nawk以 开头@/和结尾的值/会被特殊处理除非在 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的值)。$incawkstsystem("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

相关内容