BASH 我想解释一下 if-then-else 行为

Jam*_*rne 0 freebsd scripting bash

我有这个简短的 if-then-else 脚本:

for INV in "$(ls np4178/*pdf)" ;\
do INVNUMB="$(pdfgrep -ho 'IN[0-9]{6,6}' $INV)" ; \
if [[ -z ${INVNUMB+x} ]]; \
then \
  echo "\n$INVNUMB" ; \
else \
  echo "wrong  \n$INVNUMB" ; \
fi ; \
done
Run Code Online (Sandbox Code Playgroud)

产生这个:

wrong  \nIN353886
IN353897
IN353905
IN353910
IN353902
IN353864
IN353875
IN353840
IN353862
IN353922
IN353739
IN353876
IN353920
Run Code Online (Sandbox Code Playgroud)

但是,如果我对else语句进行更改,则会得到以下信息:

for INV in "$(ls np4178/*pdf)" ;\
   do INVNUMB="$(pdfgrep -ho 'IN[0-9]{6,6}' $INV)" ; \
   if [[ -z ${INVNUMB+x} ]]; \
   then \
     echo "\n$INVNUMB" ; \
   else \
     echo "\nIN000000" ; \
   fi ; \
done
Run Code Online (Sandbox Code Playgroud)

然后我只得到这个:

\nIN000000
Run Code Online (Sandbox Code Playgroud)

为什么?如何改变else子句中的文本字符串来改变整个脚本的行为和结果?

为什么换行符\nelse子句中打印为文字?

jes*_*e_b 5

这段代码有一些缺陷。

  1. 不要解析ls。并且由于您引用了命令替换,因此每个结果都INV作为单个字符串传递。相反,您可以循环遍历 glob 结果:
for inv in np4178/*pdf; do
Run Code Online (Sandbox Code Playgroud)
  1. 您不需要该代码中的任何;'s 或\'s。事实上,它们的书写方式实际上相互抵消。 ;是一个换行符,并且\是一个转义字符,在行尾使用时转义新行。

  2. echo(通常)不解释反斜杠转义(\n),你可以使用echo -eprintf 比 echo 好

  3. 由于您已经发现您的测试构造正在检查变量是否为空,而您显然想要检查它是否为

  4. 绝对没有理由这样做${INVNUMB+x}

您想要的代码可能如下所示:

for inv in np4178/*pdf; do
    invnumb="$(pdfgrep -ho 'IN[0-9]{6,6}' "$inv")"
    if [[ -n "$invnumb" ]]; then
        printf '\n%s\n' "$invnumb"
    else
        printf '\n%s\n' "IN000000"
    fi
done
Run Code Online (Sandbox Code Playgroud)