另请参阅:字符串操作-获取某个单词后面的部分
我的脚本:
# 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_opts
bash 数组:
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
输出 - 使用单引号作为参数通常比双引号更容易 - 在双引号中,某些字符保留特殊含义( ) - 在单引号中只需处理
$
`
\
文字'
- 管道 to
tr
是不必要的。当bash
扩展未引用的替换时,它会根据 shell 变量的值将结果拆分为单独的单词IFS
(有关详细信息,请参阅手册) - 的管道
... | grep | grep | sed
通常可以用单个sed
或awk
脚本代替。从提供的原始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}')