如何构建长命令字符串?

如何构建长命令字符串?

我有一系列命令与许多管道一起使用,如下所示:

awk '{ if ($8 ~ "isad") {print $2, $5, "SE"} else {print $2, $5, "ANT"} }' "/var/log/apache2/other_vhosts_access.log" | grep -v '127.0.0.1' | tr '[' '\0' | tr [:lower:] [:upper:] | sort -t' ' -s -k3

这基本上过滤了 Apache 日志并打印三列信息。第一个列是 IP 地址,第二个是时间,第三个是字符串。输出可以根据任何列进行排序,因此,我需要使用“-m”对时间字段进行排序。排序顺序也可以颠倒。

我想要一个字符串来存储要排序的参数,并让组合的字符串得到执行。像这样的东西:

$AWK_CMD | $SORT_CMD $SORT_KEY $SORT_REV

在哪里

SORT_CMD="sort -t' '"
SORT_KEY="-k$1"      # $1 from cmd line arg
SORT_REV="$2"        # Either -r or blank

能够构建这样的字符串;当我回显时,看起来不错。问题是,如何执行?我收到一些错误,例如:

awk '{ if ($8 ~ "isad") {print $2, $5, "SE"} else {print $2, $5, "ANT"} }' "/var/log/apache2/other_vhosts_access.log" | grep -v '127.0.0.1' | tr '[' '\0' | tr [:lower:] [:upper:] | sort -t' ' -s -k3
Running ...
awk: '{
awk: ^ invalid char ''' in expression

如果“排序”排序不正确,请忽略,这是可以修复的。我想知道如何逐步构建最终的命令字符串。我尝试在脚本中执行此命令的方法是:

$final_cmd
`$final_cmd`

编辑:我尝试使用的脚本

KEY=$1      # Values {1, 2, 3}
REVERSE=$2  # Values {0, 1} 

SORT_CMD="sort -t' ' -s"
SORT_KEY="-k$KEY"
if [[ $KEY -eq 2 ]]
then
    SORT_KEY="-m -k2"
fi

if [[ $REVERSE -eq 1 ]]
then
    SORT_REV="-r"
else
    SORT_REV=
fi

final_cmd="awk '{ if (\$8 ~ \"isad\") {print \$2, \$5, \"SE\"} else {print \$2, \$5, \"ANT\"} }' $LOG_FILE '|' grep -v '127.0.0.1' '|' tr '[' '\0' '|' tr [:lower:] [:upper:] '|' $SORT_CMD $SORT_KEY $SORT_REV"

echo $final_cmd
echo "Running ..."
$final_cmd

答案1

不同的部分可以放入 shell 函数中:

awkfilter() {
    awk '{ if ($8 ~ "isad") {print $2, $5, "SE"} else {print $2, $5, "ANT"} }'
}

toupper() {
    tr '[:lower:]' '[:upper:]'
}

dosort() {
    sort -t' ' -s -k3
}

awkfilter < /var/log/apache2/other_vhosts_access.log |
  grep -vF 127.0.0.1 |
  tr '[' '\0' |
  toupper |
  dosort

那么你可以更容易地使事情可选:

dosort() {
    rev=
    if [ "$2" = "reverse" ]
    then
        rev=-r
    fi
    sort -t' ' -s -k"$1" ${rev+"$rev"}
}

当您的命令行开始变得非常长时,将其编写在脚本中并将其分成几部分(使用函数)通常非常有帮助。

答案2

当您awk '{ ... }'在 shell 提示符下或从 shell 脚本运行时,shell 会解析引号并将参数传递给awk不带引号的参数。发生的情况是,您以某种方式使用参数中的引号运行它。

编辑:随着您对问题的更新,您需要的是sh -c "$final_cmd".

答案3

在所有情况下,如果您想要执行带有保存在变量中的选项的命令,请使用支持数组的 shell。

bash例如,您的示例代码被翻译成(另请注意,变量等的扩展需要用双引号引起来),

#!/bin/bash

key=$1      # Values {1, 2, 3}
reverse=$2  # Values {0, 1} 

sort_key=()
if [ "$key" -eq 2 ]; then
    sort_key=( -m  )
fi

if [ "$reverse" -eq 1 ]; then
    key+='r'
fi

sort_key+=( -k "$key" )

set -x

awk '$8 ~ "isad" { print $2, $5, ($8 ~ "isad" ? "SE" : "ANT") }' "$log_file" |
grep -Fv '127.0.0.1'          |
tr '[:lower:][' '[:upper:]\0' |
sort -t ' ' -s "${sort_key[@]}" 

在这种特殊情况下,它可能更有意义使用函数,但数组对于保留例如不确定数量的路径名或通过修改脚本自己的命令行参数创建的命令行参数很有用。

有关的:

相关内容