我想转发第三方调度程序运行的作业的作业输出。调度程序允许我将输出插入到命令中,例如:
python script.py --job-output '{joboutput}'
其中{joboutput}
成为调度程序转发的原始作业输出。
我遇到的问题是作业输出可以包含不平衡的单引号和双引号(以及特殊字符(
,如|
等),因此将作业输出用单引号或双引号括起来都不起作用。
我浏览了许多类似的问题,但没有发现涵盖这个确切场景的问题。我将非常感谢任何建议。非常感谢!
答案1
如果该命令行由调度程序预处理,然后将其发送到 shell 执行(例如,虽然sh -c
),在用实际文本进行简单的文本替换之后{joboutput}
,那么您所要求的实际上无法完成。无论如何,不只在一根线上。
它是可以将任意(NUL 终止)字符串作为命令行参数传递(无论如何都达到某个最大长度),但在 shell 命令行上插入字符串需要遵循 shell 的语法/引用规则。
基本上,shell 有双引号、单引号和反斜杠转义。在双引号内,您需要通过在反斜杠前面添加一些字符来转义它们,因此您不能在其中放置任意字符串。在单引号内,您不需要转义任何其他内容,但单引号本身需要特殊处理。通常的方法是将引号替换为'\''
,这只是关闭带引号的字符串,插入转义的单引号,然后重新打开带引号的字符串。无论如何,有些角色需要特殊对待,这是没有办法的。必须是这样,因为 shell 需要某种方法来确定带引号的字符串结束的位置。
因此,如果您使用"{joboutput}"
and{joboutput}
替换为包含"
、$
或\
的内容`
,它就会损坏;如果你使用'{joboutput}'
and{joboutput}
替换为包含 a 的东西'
,它就会崩溃。
某些语言可能有更详细的引号,例如 Python 的"""
/ '''
,这可能会有所帮助,因为它们允许偶尔使用单独的引号或引号对,但当然仍然不完全通用,因为输出可能包含相同的"""
或'''
。
但外壳没有这些。最接近的可能是here-docs,它们由自由选择的分隔线。这将有助于嵌入几乎任意字符串,但它确实需要能够传递多行,并且相当麻烦。
如果可以使用多行命令,则如果{joboutput}
被任何不END_OF_JOB_OUTPUT
禁止解析与命令替换中的here-doc相关的shell中的错误的任何内容替换,则应该可以工作。您可以将此处的文档分隔符更改为任何其他字符串,该字符串不太可能出现在输出中。但是,由于数据在这里经过命令替换,因此其中的任何尾随换行符都会丢失。
out=$(cat <<'END_OF_JOB_OUTPUT'
{joboutput}
END_OF_JOB_OUTPUT
)
python script.py --job-output "$out"
或者不在命令替换中嵌套此处文档:
exec 9<<'END_OF_JOB_OUTPUT'
{joboutput}
END_OF_JOB_OUTPUT
out=$(cat <&9)
exec 9<&-
printf "%s\n" "$out"
如果调度程序能够直接启动该命令,而不涉及 shell,我们就不需要关心 shell 的语法。调度程序只需要有一些智能来显式传递script.py
和--job-output
作业输出作为不同的参数。但我们不知道它是否可以做到这一点。 (此外,在这种情况下,您不会在占位符周围使用引号。)
另一种比上面的 shell 恶作剧更容易的方法是通过环境变量或文件传递字符串(如果调度程序支持的话)。