从bash输出中删除尾部的“,”
我有一个解析命令的脚本:从bash输出中删除尾部的“,”,bash,Bash,我有一个解析命令的脚本: while read line; do # The third token is either IP or protocol name with '[' token=`echo $line | awk '{print $3}'` last_char_idx=$((${#token}-1)) last_char=${token:$last_char_idx:1} # Case 1: It is
while read line; do
# The third token is either IP or protocol name with '['
token=`echo $line | awk '{print $3}'`
last_char_idx=$((${#token}-1))
last_char=${token:$last_char_idx:1}
# Case 1: It is the protocol name
if [[ "$last_char" = "[" ]]; then
# This is a protocol. Therefore, port is token 4
port=`echo $line | awk '{print $4}'`
# Shave off the last character
port=${port::-1}
else
# token is ip:port. Awk out the port
port=`echo $token | awk -F: '{print $2}'`
fi
PORTS+=("$port")
done < <($COMMAND | egrep "^TCP open")
for p in "${PORTS[@]}"; do
echo -n "$p, "
done
问题是尾部斜杠,
如何使最后一个端口
在输出中没有尾随的,
谢谢
${array[*]}
使用IFS
中的第一个字符连接元素
IFS=,
echo "${PORTS[*]}"
如果您不想更改IFS,可以改为使用:
printf -v ports_str '%s,' "${PORTS[@]}"
echo "${ports_str%,}"
…或者,从以下内容简化为:
…如果您不想在最后一个端口后添加尾随换行符,请将
echo
更改为printf“%s'${ports\u str%,}”
。(echo-n
不推荐;请参阅应用程序用法中的讨论)。${array[*]}
使用IFS
中的第一个字符连接元素
IFS=,
echo "${PORTS[*]}"
如果您不想更改IFS,可以改为使用:
printf -v ports_str '%s,' "${PORTS[@]}"
echo "${ports_str%,}"
…或者,从以下内容简化为:
…如果您不想在最后一个端口后添加尾随换行符,请将echo
更改为printf“%s'${ports\u str%,}”
。(echo-n
不建议使用;请参阅的应用程序用法中的讨论)。为什么不简单:
( for p in "${PORTS[@]}"; do
echo -n "$p, "
done ) | sed -e 's/,$//'
为什么不简单地:
( for p in "${PORTS[@]}"; do
echo -n "$p, "
done ) | sed -e 's/,$//'
怎么样
$ echo "${ports[@]}" | tr ' ' ','
怎么样
$ echo "${ports[@]}" | tr ' ' ','
不会回答您当前的问题,但如果您将
读取行
更改为读取f1 f2标记f4
,则效率会更高--如果您让读取
执行拆分,则不再需要awk
,然后您可以根据测试从$f4
或$f2
分配端口。谢谢。你能帮我处理这个请求吗?…另一方面,$COMMAND |……
有很多问题;请参见描述原因和各种表现更好的备选方案。你也可以考虑使用小写名称来为你自己的变量——所有的CAP名称用于对shell和操作系统的工具有意义的变量,如POSIX @指定的关于<代码> ECHO-N“${SARD[0 ] }”;未设置数组[0];对于“${array[@]}”中的p;do echo-n“,$p”;完成
?@StefanHamcke,这可能是printf'%s'${array[0]};printf',%s'${array[@]:1}“
;无需任何echo
s、显式循环,也无需更改数组。这就是说,这是一个很好的方法,如果你不介意的话,我会把它放在我的答案中。它不会回答你眼前的问题,但是如果你把read line
改为read f1 f2 token f4
——如果你让read
进行拆分,就不需要更多的awk
,然后您可以根据测试从$f4
或$f2
分配端口。谢谢。你能帮我处理这个请求吗?…另一方面,$COMMAND |……
有很多问题;请参见描述原因和各种表现更好的备选方案。你也可以考虑使用小写名称来为你自己的变量——所有的CAP名称用于对shell和操作系统的工具有意义的变量,如POSIX @指定的关于<代码> ECHO-N“${SARD[0 ] }”;未设置数组[0];对于“${array[@]}”中的p;do echo-n“,$p”;完成
?@StefanHamcke,这可能是printf'%s'${array[0]};printf',%s'${array[@]:1}“
;无需任何echo
s、显式循环,也无需更改数组。也就是说,这是一种很好的方法,如果你不介意的话,我会把它加入我的答案中。这是相当低效的——Paren创建一个子shell(因此fork()
ing关闭一个新的进程),管道需要另一层子进程创建,然后使用sed
意味着我们是fork()
ing另一个子进程,只使用execve()
syscall将其替换为一个外部程序。我对这个评论有点困惑。亚毫秒的效率是人们一直在寻找的吗?这个解决方案很简单,即使它可能不是最有效的。其他解决方案当然也是值得的。Shell脚本以速度慢著称——在某些方面被描述为太慢,甚至不适合在启动时启动服务的传统角色。它们之所以被视为慢的部分原因是,由于广泛使用极为低效的实践,它们通常比需要的慢几个数量级(字面上说,大约慢100倍)。教授好的实践,无论它们是否立即相关,都意味着更多的人将使用这些实践,因此在实践中可以高效地编写更多的脚本;对于基于Stefan对问题的评论的两种printf配方,100次运行都是0.005s。简单、易于理解和维护也是重要目的。并非所有脚本都需要优化才能达到超高效。在实用程序脚本上获得0.001秒可能并不总是值得的。这是相当低效的——paren创建一个子shell(因此fork()
关闭一个新进程),管道需要另一层子进程创建,然后使用sed
意味着我们是fork()
ing另一个子进程,只使用execve()
syscall将其替换为一个外部程序。我对这个评论有点困惑。亚毫秒的效率是人们一直在寻找的吗?这个解决方案很简单,即使它可能不是最有效的。其他解决方案当然也是值得的。Shell脚本以速度慢著称——在某些方面被描述为太慢,甚至不适合在启动时启动服务的传统角色。它们之所以被视为慢的部分原因是,由于广泛使用极为低效的实践,它们通常比需要的慢几个数量级(字面上说,大约慢100倍)。教授好的实践,无论它们是否立即相关,都意味着更多的人将使用这些实践,因此更多的脚本将在实践中高效编写