【问题标题】:AWK doesn't work in Bash ScriptAWK 在 Bash 脚本中不起作用
【发布时间】:2023-04-13 17:02:01
【问题描述】:

我在脚本中有以下 AWK 语句:

grep -E $city $DATFILE | awk -F "[\t]+" '($3 >= $minbed) && ($4 >= $minsqft) && ($5 <= $maxprice) && ($6 <= $maxweeks)' $DATFILE | sort -nk5 | less

当我运行脚本时,输出为空白。但是,如果我运行以下命令:

grep -E Toronto listing.dat | awk -F "[\t]+" '($3 >= 2) && ($4 >= 500) && ($5 <= 900000) && ($6 <= 10)' listing.dat | sort -nk4 | less

它按预期输出。

我不知道为什么会这样,我什至替换了脚本中的 awk 语句来回显变量,以确保它们正确传递并且它们是正确的。

这是目前为止的脚本:

    #!/bin/bash

    DATFILE=listing.dat

    if [ -f ${DATFILE} ];
    then

            echo -n "Are you looking into anywhere in the GTA, or a specific city?: "
            read uinput

            if [ $uinput == "anywhere" ];
            then
                    echo "You have chosen anywhere"
            elif [ $uinput == "specific" ];
            then
                    echo -n "Which city?: "
                    read city

                    echo -n "Minimum Number of Bedrooms: "
                    read minbed

                    echo -n "Minimum Square Footage (500, 600, etc): "
                    read minsqft

                    echo -n "Maximum Price: "
                    read maxprice

                    echo -n "Maximum Weeks On Market: "
                    read maxweeks

                    echo -n "Sort by (price, sqrft, weeks): "
                    read sortby

                    if [ $sortby == "price" ];
                    then
                            echo -n "Sort by (asc, desc): "
                            read ascdesc
                            if [ $ascdesc == "asc" ];
                            then
                                    grep -E $city $DATFILE | awk -F "[\t]+" '($3 >= $minbed) && ($4 >= $minsqft) && ($5 <= $maxprice) && ($6 <= $maxweeks)' $DATFILE | sort -nk5 | less
                        elif [ $ascdesc == "desc" ];
                        then
                                grep -E $city $DATFILE | awk -F "[\t]+" '($3 >= $minbed) && ($4 >= $minsqft) && ($5 <= $maxprice) && ($6 <= $maxweeks)' $DATFILE | sort -rnk5 | less
                        fi
                fi

        fi

else
        echo "${DATFILE} Not found!"
fi

你能帮忙吗?

谢谢

【问题讨论】:

  • gawkawk?你的例子中都有。
  • 您的 awk 脚本用单引号括起来。 Shell 变量在单引号内时不会展开。所以你需要使用 -v 将它们分配给一个 awk 变量。
  • 无论如何,不​​要将 grep 结果通过管道传输到 awk。 awk 本身可以通过正则表达式过滤
  • @JerryJeremiah 你能给我举个例子吗?
  • 您将 awk 的分隔符设置为 "[\t]+",这将匹配多个制表符。但是 sort 使用任何空格,因此您可能需要使用 -t 将用于排序的字段分隔符设置为与用于 awk 的值相同的值。

标签: linux bash shell awk


【解决方案1】:

如果您不熟悉任何 *nix 实用程序,您可以使用“man utility_name”查看基本文档;来自“awk”的手册页(man awk):

-v var=val
在程序开始执行之前,将值 val 赋给变量 var。这些变量值可用于 BEGIN 块 AWK 程序。

还有其他方法可以做到这一点,但按照文档,您的代码将更改为:

awk -F "[\t]+" \  
  -v MINBED=$minbed -v MINSQFT=$minsqft -v MAXPRICE=$maxprice -v MAXWEEKS=$maxweeks \
  '($3 >= MINBED) && ($4 >= MINSQFT) && ($5 <= MAXPRICE) && ($6 <= MAXWEEKS)'  

【讨论】:

  • 好的,这很棒。它工作得很好,但是我现在不能让它按城市过滤。在脚本中使用 egrep 并将其传递到 awk,它会显示所有城市。如果我从脚本中直接运行相同的命令并进入终端,它就可以工作....有什么想法吗?
  • 从您的 awk 命令字符串中删除“$DATAFILE”;来自 grep 的“管道”(匹配)直接发送到“awk”-如果您包含文件名,“awk”将打印文件中的所有内容... [它忽略来自“管道”的数据]...
【解决方案2】:

由于声誉问题,我还不能发表评论。您可以做的另一件事是转义变量名周围的单引号。如果您仍然无法显示所有城市,我相信这是因为您为 awk 提供了文件名。看起来你需要把它拿出来,让 grep 的输出用作 awk 的输入。我无法访问我的 linux 机器来测试它,但是:

您的行(提供了两次 $DATFILE):

grep -E $city $DATFILE | awk -F "[\t]+" '($3 >= $minbed) && ($4 >= $minsqft) && ($5 <= $maxprice) && ($6 <= $maxweeks)' $DATFILE;

选项1:删除第二个$DATFILE,转义单引号

grep -E $city $DATFILE | awk -F "[\t]+" '($3 >= '$minbed') && ($4 >= '$minsqft') && ($5 <= '$maxprice') && ($6 <= '$maxweeks')';

选项 2:您可以使用转义的单引号完全摆脱 grep。 awk 的 IGNORECASE 应该替代 grep 的 -E。

awk -F "[\t]+" 'IGNORECASE = 1;/'$city'/&&($3 >= '$minbed')&&($4 >= '$minsqft')&&($5 <= '$maxprice')&&($6 <= '$maxweeks')';

就像我说的,目前无法测试它的语法;希望对你有帮助。

黑客愉快!

【讨论】:

    最近更新 更多