Shell 动态变量作为 AWK 内的条件

问题描述 投票:0回答:1

我有一个

sh
(POSIX) 脚本,我试图从主机列表 (SSH) 中选择一个主机,该列表在主机名称中包含一些有趣的信息,例如可用的可用内存、已连接的用户。 .我希望我的脚本的用户选择脚本应考虑哪些特征,以便从所述列表中选择合适的主机。

由于此特征是可选的,因此我的想法是根据用户选择的选项在 shell 变量(仅文本)中构建条件语句。然后,将此变量传递给 AWK 以提取那些合适的主机并随机选择其中之一。目前,saild 语句或

FILTER
可能如下所示:

FILTER='$6 <=MAXUSERS && $7 <=MAXUSERS'
FILTER='$6 <=MAXUSERS && $7 <=MAXUSERS && $9 >=10'
FILTER='$6 <=MAXUSERS && $7 <=MAXUSERS && $9 >=10 && $11 >=8'

($X 只是位置参数,作为主机的特征,我知道它们的位置,只要 HTML 源代码不改变,就不应该改变)我用这段代码构建这些语句:

setUpFilter(){
    FILTER='$6 <=MAXUSERS && $7 <=MAXUSERS'
    if [ -n "$CPUNUM" ]; then
        FILTER="${FILTER} && \$9 >=$CPUNUM"
    fi
    if [ -n "$FREEMEM" ]; then
        FILTER="${FILTER} && \$12 >=$FREEMEM"
    fi
}

一旦构建了语句,我就使用这个:

filterHosts(){
    setUpFilter
    for HOST in $(echo "$AVAILABLEHOSTS"); do # $AVAILABLEHOSTS is a list with only the hosts names
        HOSTDATA=$(echo "$REPORTCLEAN" | egrep -A 11 "$HOST") # Report clean is a list of hosts and its data extracted from an HTML file
        FILTEREDHOSTS=${FILTEREDHOSTS}$(echo $HOSTDATA | awk -v FILTER="$FILTER" -v MAXUSERS=5 '{
            if (FILTER)
                print $1 "\\n"
        }')
    done
}

然而,这并没有按预期工作,因为“过滤器”似乎什么也没做,因为所有主机都存储在

$FILTEREDHOSTS
中,就像所有迭代中的条件都是
true
一样(我不确定为什么),但是当我在 AWK 脚本中手动设置条件时,“过滤器”按预期工作:

filterHosts(){
    setUpFilter
    for HOST in $(echo "$AVAILABLEHOSTS"); do # $AVAILABLEHOSTS is a list with only the hosts names
        HOSTDATA=$(echo "$REPORTCLEAN" | egrep -A 11 "$HOST") # Report clean is a list of hosts and its data extracted from an HTML file
        FILTEREDHOSTS=${FILTEREDHOSTS}$(echo $HOSTDATA | awk -v MAXUSERS=5 '{
            if ($6 <=MAXUSERS && $7 <=MAXUSERS && $9 >=10)
                print $1 "\\n"
        }')
    done
}

$HOSTDATA
看起来像这样,顺便说一句:
HOSTNAME PARAM2 PARAM3 ... PARAM12
,所以我想根据与某些值匹配的一些参数来检索
$1
(主机名)。

我知道第二段代码有效,因为我在执行它后手动检查了列表。

我尝试过 AWK 打印

FILTER
,显然该声明是正确的,因为它的打印效果就像我上面写的第一个示例一样,没有任何扩展或意外的东西,就像示例一样。

我不太擅长 AWK,所以我不知道会发生什么,我什至不确定这是否是 AWK 的问题。另一方面,我想知道这是否是我想要实现的目标的最佳方法。

提前致谢。

更新

正如一些用户建议的那样,我将内置的“过滤器”移至 awk 脚本本身,所以我最终得到了这个:

filterHosts(){
    for HOST in $(echo "$AVAILABLEHOSTS"); do
        HOSTDATA=$(echo "$REPORTCLEAN" | egrep -A 11 "$HOST")
        FILTEREDHOSTS=${FILTEREDHOSTS}$(echo $HOSTDATA | awk -v cpunum="$CPUNUM" -v freemem="$FREEMEM" -v MAXUSERS="$1" '{
            filter = $6 <=MAXUSERS && $7 <=MAXUSERS
            if (length(cpunum) != 0)
                filter = filter && $9 >= cpunum
            if (length(freemem) != 0)
                filter = filter && $12 >= freemem
            if (filter)
                print $1 "\\n"
        }')
    done
}

显然,乍一看,这没有问题,所以我认为这个问题“半解决”,因为我不确定为什么前面的代码不起作用,但我有一段不同的代码可以工作。

if-statement awk sh
1个回答
0
投票

您的“半最终”解决方案受到无用使用

echo
的困扰,可以重构为

filterHosts(){
    for host in $AVAILABLEHOSTS; do
        hostdata=$(echo "$REPORTCLEAN" | egrep -A 11 "$host")
        filteredhosts=${filteredhosts}$(echo $hostdata |
        awk -v cpunum="$CPUNUM" -v freemem="$FREEMEM" -v MAXUSERS="$1" '{
            filter = $6 <=MAXUSERS && $7 <=MAXUSERS
            if (length(cpunum) != 0)
                filter = filter && $9 >= cpunum
            if (length(freemem) != 0)
                filter = filter && $12 >= freemem
            if (filter)
                print $1 "\\n"
        }')
    done
}

echo $hostdata
周围缺少引号会将
egrep
结果扁平化到单行上,这通常是一个错误;但如果无法访问这些数据,我无法相应地重构 Awk 脚本。

https://stackoverflow.com/questions/673055/ Correct-bash-and-shell-script-variable-capitalization解释了为什么所有变量都使用小写。理想情况下,脚本的其余部分应该类似地重构。

© www.soinside.com 2019 - 2024. All rights reserved.