SED 失败,为什么?

SED 失败,为什么?

另请参阅:字符串操作-获取某个单词后面的部分

我的脚本:

    # get list of curent possible F2B 'get' options, as a array (omitting the 'action..') ..
    f2b_opts_cmd="$(sudo fail2ban-client --help | grep -i 'get <jail>' | grep -vw 'act')"
    f2b_opts="$(sed -e "s/get\s<JAIL>\s\([^ ]*\).*/\1/" $f2b_opts_cmd | tr '\n' ' ')"
    echo $f2b_opts`  

我做错了什么?这段代码只给了我一整行“sed:无法读取..”行?

顺便说一句,如果我使用管道构造:f2b_opts_cmd="$(sudo fail2ban-client --help | grep -i 'get <jail>' | grep -vw 'act' | sed -e "s/get\s<JAIL>\s\([^ ]*\).*/\1/" | tr '\n' ' ')" 它会包含我认为已被过滤掉的“操作”行?(在命令行上执行时,它不会包含那些“操作”行)

答案1

编辑:刚刚读了你之前的问题,其中提到了一个数组变量。要将其f2b_opts_cmd作为字符串变量和f2b_optsbash 数组:

f2b_opts_cmd=$(fail2ban-client -h | awk '/get <JAIL>/ && !/<ACT>/')
f2b_opts=( $(awk '{print $3}' <<< "$f2b_opts_cmd") )
echo "${f2b_opts[@]}"

为什么以下方法不起作用:

# get list of curent possible F2B 'get' options, as a array (omitting the 'action..')
f2b_opts_cmd="$(sudo fail2ban-client --help | grep -i 'get <jail>' | grep -vw 'act')"

f2b_opts="$(sed -e "s/get\s<JAIL>\s\([^ ]*\).*/\1/" $f2b_opts_cmd | tr '\n' ' ')"
:                                                   ^
echo $f2b_opts
  • 参数扩展$f2b_opts_cmd提供了要读取的文件列表sed。相反,将参数扩展的结果直接发送到标准输入sed
f2b_opts=$(sed -e 's/get\s<JAIL>\s\([^ ]*\).*/\1/' <<EOF
$f2b_opts_cmd
EOF
)

bash提供了一个比上述更简洁的替代方案<< 此处文档重定向,也称为此处字符串

f2b_opts=$(sed -e 's/get\s<JAIL>\s\([^ ]*\).*/\1/' <<<"$f2b_opts_cmd")
  • grep -vw 'act'不起作用,因为您要过滤掉的行是大写 ( <ACT>)。使用-i忽略大小写,或指定具有适当大小写的模式grep -vw 'ACT'
    • 至于为什么它在命令行上尝试时有效——我只能猜测你可能已经grep别名为grep -i
  • 无需sudo查看--help输出
  • 使用单引号作为参数通常比双引号更容易 - 在双引号中,某些字符保留特殊含义( ) - 在单引号中只需处理$ ` \文字'
  • 管道 totr是不必要的。当bash扩展未引用的替换时,它会根据 shell 变量的值将结果拆分为单独的单词IFS(有关详细信息,请参阅手册)
  • 的管道... | grep | grep | sed通常可以用单个sedawk脚本代替。从提供的原始sed脚本反向操作:
f2b_opts=$(fail2ban-client -h | \
    sed -nE '/get <JAIL>/{/<ACT>/!s/(\s*\S*){3}.*/\1/p;}')

awk似乎更容易使用这个:

f2b_opts=$(fail2ban-client -h | awk '/get <JAIL>/ && !/<ACT>/{print $3}')

相关内容