打印包含空格和特殊字符的最后一列

我需要一个完整的path/命令来启动一个在networking上暴露的进程 – 在tcp / udp上监听。 我设法使用下面的“单线”来解决所有这些问题:

netstat -nlp46|tail -n +3 | while IFS=" " read -r -a line; do nb=${#line[@]}; PID=$(echo ${line[$((nb - 1))]} | awk -F'/' '{print $1}'); CMD=$(ps -ef|awk '$2 == '"$PID" |awk -F" " '{out=$8; for(i=9;i<=NF;i++){out=out""$i}; print out}'); echo $PID^$CMD; done 

但是当进程在命令行中包含一些特殊字符,例如瘦服务器时,脚本会出现一些跟随错误的问题

 awk: line 1: missing ) near end of line 

当我在这个过程中运行脚本的一部分时,我没有任何问题

 root@ftp-host02:~# PID=15000; COMMAND=$(ps -ef|awk '$2 == '"$PID" |awk '{out=$8; for(i=9;i<=NF;i++){out=out" "$i}; print out}'); echo $COMMAND thin server (0.0.0.0:3000) 

我在这里做错了什么?

谢谢

错误在这里: awk '$2 == '"$PID"

  • 如果$PID不是严格的数字,那么你对一个没有引号的string进行了等式检查,所以真的,谁知道awk将如何解释呢?

     $ PID="3000)" $ echo hello | mawk '$2 == '"$PID" mawk: line 1: extra ')' 

将shellvariables传递给awk作为awkvariables(使用-v选项)会将其清除。

以其他方式清理你的代码,我们有:

 netstat -nlp46 | tail -n +3 | while IFS=" " read -r -a fields; do nb=${#fields[@]} PID=${fields[nb-1]%%/*} CMD=$( ps -ef | awk -v pid="$PID" '$2 == pid {out=$8; for(i=9;i<=NF;i++){out=out $i}; print out}' ); echo "$PID^$CMD"; done 

笔记:

  • 正确的缩进对可读代码有很大的帮助
  • 数字索引数组的索引已经在算术上下文中进行了评估,因此${ary[n-1]}将起作用
  • 你可以删除一个斜杠和所有随后的shell参数扩展的字符,所以你不需要awk来获得PID
  • 你不需要awk的awk:巩固
  • -v选项将一个shellvariables传递给awk

你可以试试这个:

for i in $(netstat -atnp | awk '{ print $7 }' | grep ^[0-9] | awk -F\/ '{ print $1 }'); do echo "PID: $i " $(ps faxuwwww | grep $i); done