bash 脚本中的意外输出。而不是文字“?”,有回显 "d" 和 "i"

Unexpected output in bash script. Instead of the literal "?", there is echoed "d" and "i"

我有以下代码片段:

#!/bin/bash
clear
echo "PS to AWK"

read prg

check=($(ps -e | grep $prg | awk '{print "kILL " " " " ? [y/n]"}'))

echo "${check[@]}"

假设的输出应该是:

PS to AWK
auda
kILL audacious 2423 ? [y/n]

但不幸的是我的输出是这样的:

PS to AWK
auda
kILL audacious 2423 d i [y/n]

有人提示问号丢失的原因以及 "d" 和 "i" 的来源?

提前感谢您的回答。

未加引号的 ? 被 shell 扩展为通配符。当前目录下有两个单字符文件名。

解决方法是通常引用所有内容,除非您特别要求 shell 对值执行通配符扩展和空格标记化。

通配符在数组赋值中得到扩展,因此您可以引用:

check=("$(ps -e | awk -v prg="$prg" '[=10=] ~ prg {print "kILL " " " " ? [y/n]"}')")

但是你可能不会使用数组。但是你也可以只捕获 PID。

pid=$(ps -e | awk -v prg="$prg" '[=11=] ~ prg { print  }')

不过,这会丢失进程名称。您可以重构脚本以仅打印机器可读部分,然后在打印语句中使用它们。

check=($(ps -e | awk -v prg="$prg" '[=12=] ~ prg { print ,  }'))
read -p "kILL ${check[1]} ${check[0]}? [y/n]"

(顺便说一句,将问号与前一个词对齐,就像英语正字法中的惯例一样,也可以解决您的问题,尽管有点意外。另请注意如何避免示例中的 useless use of grep以上。)

不要使用命令替换的输出(经过 glob 扩展和单词复制)来填充 shell 数组 check,而应该像这样使用 read 和进程替换:

read -ra check < <(ps -e | awk -v p="$prg" '[=10=] ~ p{print "kILL " " " " ? [y/n]"}')

然后使用以下方法检查结果:

echo "${check[@]}"

# or
declare -p check