【问题标题】:AWK: parsing arguments in a loopAWK:在循环中解析参数
【发布时间】:2014-11-16 15:51:01
【问题描述】:

我正在尝试编写一个简单的脚本,它将用户指定的字段显示为 bash 参数。例如,我的文本文件如下所示:

1 2 3 4 5
1 2 3 4 5
a b c d e

例如用户类型:

./script.sh text 1 2 5

其中 $1 = 文本,其他参数(如 $2 $3 和 $4)是字段,因此输出将如下所示:

1 2 5
1 2 5
a b e

我有这段代码,它打印所有定义为参数的列,但在其他列之下:

#!/bin/bash

text="$1"
shift

for x in $@; do
awk '{print $var}' var="$x" $text
done

输出例如 ./script.sh text 1 2 5:

1
1
a
2
2
b
5
5
e

我猜输出看起来像这样,因为循环“for”在 AWK 之外。将循环放置在 AWK 中是否是一个很好的解决方案?我尝试了一些东西,但语法总是有问题。

感谢您的宝贵时间和帮助!

【问题讨论】:

    标签: bash for-loop awk parameters arguments


    【解决方案1】:
    file="$1"
    shift
    awk -v flds="$*" 'BEGIN{n=split(flds,f)} {for (i=1;i<=n;i++) printf "%s%s", $(f[i]), (i<n?OFS:ORS)}' "$file"
    

    【讨论】:

    • 非常感谢您的回复。我会尝试分析这两个答案:)。
    • 您应该将 BlueMoons 的答案选中为已接受,因为他的想法是正确的,但您应该在实际代码中使用我的答案。
    【解决方案2】:

    您不需要遍历参数,将它们全部传递给 awk 并使用 -v 选项:

    awk -v v1=$2 -v v2=$3 -v v3=$4 '{print $v1, $v2, $v3;}' $1
    

    您可能想要执行额外的检查,例如文件 ($1) 是否包含足够的字段、文件 ($1) 是否存在等。但想法是一样的。

    在您的代码中,您多次读取文件,每次仅检查特定字段,但要获得所需的输出,必须同时检查每一行的多个字段。


    将列传递给 awk 并将它们拆分为一个数组并打印与数组中每个值对应的列:

    file=$1
    shift
    p="$@"
    awk -v l="$p" '{t=split(l,a," "); for (i=1;i<=t;i++) printf $(a[i]) " ";printf "\n";}' $file
    

    【讨论】:

    • 嗨!感谢您的回复。我尝试过类似的解决方案,但如果用户只输入 1 个或 2 个或仅输入 6 个参数,它就不起作用。它仅适用于 3 个参数,我希望它“灵活”。
    • 您可以将所有列号传递给awk 以使用数组,然后打印这些列。
    • 哇!是的,它确实有效。谢谢你的帮助,现在我必须明白这一点:)。
    • 第二个脚本的想法是正确的,但是:不需要将默认 FS 指定为 split() 的第三个参数,对每个输入行执行 split() 效率低下,永远不要使用 printf $N 使用printf "%s", $N 相反,如果输入包含例如 %s,则无需显式打印 ORS,这将在每个输出行添加一个虚假的尾随空白,打印字段时无需硬编码默认 OFS 值,否需要尾随分号,并且永远不要使用字母 l 作为变量名,因为它看起来太像数字 1
    猜你喜欢
    • 2022-10-15
    • 2017-03-25
    • 2016-10-30
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    相关资源
    最近更新 更多