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

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

我有这个简短的 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

产生这个:

wrong  \nIN353886
IN353897
IN353905
IN353910
IN353902
IN353864
IN353875
IN353840
IN353862
IN353922
IN353739
IN353876
IN353920

但是,如果我对声明进行更改,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

然后我只得到这个:

\nIN000000

为什么?更改子句中的文本字符串如何才能使else脚本的整个行为和结果发生改变?

为什么换行符\n在子句中打印为文字else

答案1

这段代码存在一些缺陷。

  1. 不解析ls。由于您已引用命令替换,因此每个结果都会INV作为单个字符串传递。相反,您可以只循环遍历全局结果:
for inv in np4178/*pdf; do
  1. 您不需要该代码中的任何;或。\事实上,它们的书写方式实际上是相互抵消的。 ;是换行符分隔符,也是\转义字符,在行尾使用时会转义新行。

  2. echo(通常)不会解释反斜杠转义符(\n),您可以使用echo -e但是printf 比 echo 更好

  3. 正如您已经发现的那样,您的测试构造正在检查变量是否null 当你显然想检查它是否不是无效的

  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

答案2

感谢您的所有帮助。这非常有用。显然,我给出的示例并不是完整的脚本。而且我不理解用 括起环境变量的意义"",所以吸取了教训。这是我理解这个问题的早期尝试,所以我对我到底想要完成什么感到有些困惑。

我将其发布为正确设置代码格式的答案。以下或多或少是我最终得到的结果:

for INV in $(ls -1 $SRCDIR/HP3000-INV*pdf)
# search files for IN###### and return only first occurrence of match
do INVNUMB="$(pdfgrep -h -o -m 1 'IN[0-9]{6,6}' $INV)"
  if [[ -n ${INVNUMB} ]]; \
    then
      # prepend the invoice number to the file name
      # and move renamed file to xfr directory
      mv -f $INV $(dirname $INV)"/"$TODAY"/"$INVNUMB"-"$(basename $INV)
  fi
done

相关内容