首页 > 解决方案 > 如何在bash中使用变量将裁剪字符串参数传递给cpdf

问题描述

这个问题是关于如何在 bash 中(并且不能)将字符串(包含在 bash 变量中)作为参数传递给二进制可执行文件。我正在使用一个特定的二进制可执行文件,但问题更广泛,因为我们可能希望将字符串参数传递给各种二进制可执行文件。

我知道下面描述的行为对于我正在调用的二进制可执行文件可能非常特殊。但我怀疑我所描述的反映了 bash 工作原理的基本原理,在这种情况下,它可能会引起少数人的兴趣。

背景

这个问题出现在我编写一个使用cpdf (link)的 bash 脚本的过程中,它是一个二进制可执行文件。该程序cpdf是开源的;源代码(在 OCaml 中)可在此处获得。

相关二进制可执行文件的基本用法

假设,在 bash 终端中,工作目录包含一个名为in.pdf.

然后以下命令会生成一个名为的 pdf 文件,out.pdf其中包含来自以下位置的裁剪窗口in.pdf

cpdf -crop "10pt 10pt 200pt 500pt" in.pdf -o out.pdf

裁剪的大小由字符串指定"10pt 10pt 200pt 500pt"(为了完整性:如果裁剪窗口的左下角在 (x1,y1) 和右上角为 (x2,y2),则字符串格式为 x1 y1 x2 y2——加上单位,全部用引号括起来。)

使用变量传递裁剪字符串

以下将起作用:

cropstring="10pt 10pt 200pt 500pt"
cpdf -crop "$cropstring"  $filein -o out1.pdf

但以下不会:

cropstring="\"10pt 10pt 200pt 500pt\""
cpdf -crop $cropstring  $filein -o out2.pdf

如果你执行后者,它会返回错误信息

Bad rectangle specification "10pt

不同之处在于,在第一种情况下,封闭的引号不是包含在变量中的字符串的一部分cropstring,而在第二种情况下,它们是其中的一部分。

问题

这种行为可能是非常特定的cpdf,还是反映了 bash 的一些一般属性?如果是后者,那么还有两个问题:为什么第二种方法不起作用?有没有办法定义变量cropstring,以便第二种方式(意思是,所有必需的引号都以某种方式包含在变量的内容中)有效?

标签: stringbashvariables

解决方案


您在这里遇到的问题是它cpdf不是像echoor之类的字符串解释器printf。在您的情况下,您cpdf不知道如何解释您的转义字符串,并且当您将这个“所谓的”变量(cropstring)传递给 cpdf 二进制文件时,您实际上是这样告诉 bash:将这个参数传递给 cpdf 脚本,在该参数中关闭双引号在 \"10pt 你有一个空格之后,这意味着 cpdf 跳转到下一个参数(输入文件)并离开这部分字符串 10pt 200pt 500pt\" (这意味着你的脚本将 10pt 作为单个参数,这是不幸的,因为你的二进制脚本需要其他 3 个参数) . 这就是为什么您的二进制文件会引发错误,因为它无法裁剪只有一个参数的窗口10pt。它期望字符串中有3 个参数.

这就是您的二进制脚本将如何退出(出现错误)并告诉您存在Bad rectangle specification "10pt.

您传递给 cpdf 的参数在第一个示例中很好,但在第二个示例中是错误的。我之前描述了 bash 如何解释参数。在第一个示例中,您的二进制脚本将cropstring其视为字符串变量,在第二个示例中,它将仅传递第一个参数,即10pt.

为了回应您的回答,这是 bash 解释字符串和脚本的方式,而不是 cpdf 二进制文件的问题。

你写的那一行: cropstring="\"10pt 10pt 200pt 500pt\"" 只能由文本解释器很好地解释(你可以玩写作echo -e $cropstring),但永远不能在 bash 命令行中解释。当您将变量作为参数传递给某个 bash 脚本时,bash 会看到您的变量,例如cpdf -crop ""10pt. 这都是因为字符串的其余部分将被视为 file.in 参数。发生错误是因为您的裁剪参数要求的字符串参数仅为 10pt,因此二进制文件不知道如何裁剪该窗口。


推荐阅读