变量中包含空格的参数的命令选项
当我运行以下bash脚本时:
options="--nup 2x2 --column true --columnstrict true"
pdfjam inp.pdf '1-8' $options --offset '0mm 1mm' --outfile out.pdf
一切都运行正常,我得到了输出:
----
pdfjam: This is pdfjam version 3.10.
pdfjam: Reading any site-wide or user-specific defaults...
(none found)
pdfjam: Effective call for this run of pdfjam:
/usr/bin/pdfjam --nup '2x2' --column 'true' --columnstrict 'true' --offset '0mm 1mm' --outfile out.pdf -- inp.pdf 1-8
pdfjam: Calling /usr/bin/pdflatex...
pdfjam: Finished. Output was written to 'out.pdf'.
当我把偏移量放入选项中:
options="--nup 2x2 --column true --columnstrict true --offset '0mm 1mm'"
pdfjam inp.pdf '1-8' $options --outfile out.pdf
我得到错误信息:
----
pdfjam: This is pdfjam version 3.10.
pdfjam: Reading any site-wide or user-specific defaults...
(none found)
pdfjam ERROR: no PDF/JPG/PNG file found at 1mm'
所以我猜 0mm 与 1mm 之间的空格会导致麻烦。
尝试将 $options 放在双引号中:
pdfjam inp.pdf '1-8' "$options" --outfile out.pdf
结果是:
----
pdfjam: This is pdfjam version 3.10.
pdfjam: Reading any site-wide or user-specific defaults...
(none found)
pdfjam: Effective call for this run of pdfjam:
/usr/bin/pdfjam --nup 2x2 --column true --columnstrict true --offset '0mm 1mm' '--outfile' -- inp.pdf 1-8 out.pdf -
pdfjam: Calling /usr/bin/pdflatex...
pdfjam: FAILED.
The call to /usr/bin/pdflatex resulted in an error.
If '--no-tidy' was used, you can examine the
log file at
/tmp/pdfjam-No0ZGo/a.log
to try to diagnose the problem.
pdfjam ERROR: Run 1: Output file not written
如何修复?
解决方案
我在系统上没有 pdfjam,所以为了演示目的我将使用以下脚本,它打印出输入参数的列表:
$ cat pdfjam
#!/bin/bash
cnt=0
for var in "$@"
do
((cnt++))
echo "arg ${cnt}:$var:"
done
要启用“调试器”,在你要调试的命令之前运行 set -x(要禁用请使用 set +x);这将显示 bash 如何展开 $options 的内容:
options="--nup 2x2 --column true --columnstrict true"
set -x # enable debugger
./pdfjam inp.pdf '1-8' $options --offset '0mm 1mm' --outfile out.pdf
set +x # disable debugger
+ ./pdfjam inp.pdf 1-8 --nup 2x2 --column true --columnstrict true --offset '0mm 1mm' --outfile out.pdf
arg 1:inp.pdf:
arg 2:1-8:
arg 3:--nup:
arg 4:2x2:
arg 5:--column:
arg 6:true:
arg 7:--columnstrict:
arg 8:true:
arg 9:--offset:
arg 10:0mm 1mm:
arg 11:--outfile:
arg 12:out.pdf:
好,这看起来不错。
注: 在本答案的其余部分,我将a) 保留 set -x 的启用状态,b) 只输出感兴趣的调试行。
现在是你的第二次尝试:
options="--nup 2x2 --column true --columnstrict true --offset '0mm 1mm'"
./pdfjam inp.pdf '1-8' $options --outfile out.pdf
+++ ./pdfjam inp.pdf 1-8 --nup 2x2 --column true --columnstrict true --offset ''\''0mm' '1mm'\''' --outfile out.pdf
arg 1:inp.pdf:
arg 2:1-8:
arg 3:--nup:
arg 4:2x2:
arg 5:--column:
arg 6:true:
arg 7:--columnstrict:
arg 8:true:
arg 9:--offset:
arg 10:'0mm: # leading single quote is part of data
arg 11:1mm': # trailing single quote is part of data
arg 12:--outfile:
arg 13:out.pdf:
从调试输出('\'')以及脚本输出(参数#10与 #11)可以看出,bash 把单引号视为数据的一部分,而不是你希望的定界符。虽然转义序列确实会导致两个偏移量被处理为一个被单引号包裹的字符串(''\''0mm' '1mm'\''' == ''1mm 0mm'' => 外层引号是定界符,内层引号是数据),但因为 $options 未用双引号包裹,我们得到 bash 的常规行为,即按空白字符分割,因此单个输入字符串 - '0mm 1mm' - 变成了两个独立的字符串 - '0mm 和 1mm'。
正如Wiimm在他们的回答中所演示的,你想做的是将每一项(选项名、选项值)作为数组中的单独条目存储。但这种方法有一个警告……
同样,Wiimm演示的正确方法是确保你用双引号包裹数组引用:
./pdfjam inp.pdf '1-8' "${options[@]}" --outfile out.pdf
^^^^^^^^^^^^^^^----- double quotes wrapper
+ ./pdfjam inp.pdf 1-8 --nup 2x2 --column true --columnstrict true --offset '0mm 1mm' --outfile out.pdf
arg 1:inp.pdf:
arg 2:1-8:
arg 3:--nup:
arg 4:2x2:
arg 5:--column:
arg 6:true:
arg 7:--columnstrict:
arg 8:true:
arg 9:--offset:
arg 10:0mm 1mm: # array entry treated as a single string
arg 11:--outfile:
arg 12:out.pdf:
正如你所看到的,偏移值 (0mm 1mm) 被处理为一个单独的字符串。
如果你省略了双引号,那么 bash 将无法把偏移值保持为一个单独的字符串:
./pdfjam inp.pdf '1-8' ${options[@]} --outfile out.pdf
^^^^^^^^^^^^^--- missing double quotes wrapper
+ ./pdfjam inp.pdf 1-8 --nup 2x2 --column true --columnstrict true --offset 0mm 1mm --outfile out.pdf
arg 1:inp.pdf:
arg 2:1-8:
arg 3:--nup:
arg 4:2x2:
arg 5:--column:
arg 6:true:
arg 7:--columnstrict:
arg 8:true:
arg 9:--offset:
arg 10:0mm: # array entry split on white space
arg 11:1mm: # and treated as separate strings
arg 12:--outfile:
arg 13:out.pdf:
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。