shell 脚本和 shell 内执行之间有哪些区别导致这种不同的 if 行为?

shell 脚本和 shell 内执行之间有哪些区别导致这种不同的 if 行为?

在 xfce4-terminal 中我执行:

if [[ $(pgrep -x xfce4-terminal) ]]; then         echo "there are files" > test.txt;     else         echo "no files found" > test.txt;     fi

there are files它在 中写入test.txt。如果我在 shell 脚本中执行相同的操作,并在 xfce4-terminal 仍然打开时调用,它会no files found在 中写入test.txt

if [[ $(pgrep -x xfce4-terminal) ]]; then         echo "there are files" > test.txt;     else         echo "no files found" > test.txt;     fi

为什么会出现这种情况,我需要做什么才能修复这个问题(让 shell 脚本像 shell 一样运行)?

检查$(pgrep -x xfce4-terminal)

从航站楼:

echo $(pgrep -x xfce4-terminal) > toast.txt
# 8257

从 shell 脚本:

echo $(pgrep -x xfce4-terminal) > toast.txt
# 8257

答案1

扩展的测试构造[[ ... ]]首先出现在ksh,随后被包括bash和在内的其他shell复制zsh

如果你尝试在一个简单的 POSIX shell 中使用它/bin/sh(可能是因为你省略了 shebang,例如 - 请参阅哪个 shell 解释器可以运行没有 shebang 的脚本?)将导致语法错误 -if无论测试是否真实,都将导致条件失败。例如:

$ bash -c 'if [[ 1 -eq 1 ]]; then echo "equal"; else echo "not equal"; fi'
equal    

$ sh -c 'if [[ 1 -eq 1 ]]; then echo "equal"; else echo "not equal"; fi'
sh: 1: [[: not found
not equal

然而[[ $(pgrep -x xfce4-terminal) ]]并不是测试是否存在名为 的正在运行的进程的最佳实践xfce4-terminal,即使 shell 支持它。除了使用命令替换$(...)来捕获命令的标准输出pgrep并测试它是否为非空字符串之外,您还可以使用退出状态pgrep直接。来自man pgrep

EXIT STATUS
       0      One  or  more  processes  matched  the  criteria.  For pkill the
              process must also have been successfully signalled.
       1      No processes matched or none of them could be signalled.
       2      Syntax error in the command line.
       3      Fatal error: out of memory etc.

所以

if pgrep -x xfce4-terminal >/dev/null; then
  echo "there are files" > test.txt 
else  
  echo "no files found" > test.txt
fi

它可以在任何类似 Bourne 的 shell (sh、ksh、bash、zsh) 中运行。

答案2

在终端版本中,您有[[ ]],它会评估其内容,如果内容有效,则返回退出状态 0,否则返回 1。如果仅传递一个字符串,则如果字符串的长度 > 0,则返回 0,否则返回 1。由于您的命令发现了某些内容,它会返回长度 > 0 的字符串,并且返回[[ ]]状态 0 或“true”。

if在shell脚本中,使用语句的返回值if来决定是否执行thenelse。如果返回值为0,则执行then,否则跳至else

但是,如果您检查man pgrep,它会返回退出代码 1,表示“一个或多个进程符合条件。”因此,if会将其视为以非零错误代码退出,并跳至else

为了修复这个问题,只需加入[[ ]]shell 脚本版本即可。

相关内容