【问题标题】:What is the best way to tokenize bash shell command in PHP?在 PHP 中标记 bash shell 命令的最佳方法是什么?
【发布时间】:2020-01-04 18:34:34
【问题描述】:

我的情况是,我需要采用(可能)多字符串 bash 命令并将其压缩成一个不包含任何换行符或回车符的字符串(但产生相同的结果,即命令语义必须不受影响)。

以下是一些输入示例和相应的预期输出。

输入:

echo A
echo B

预期输出:

echo A;echo B

输入

echo "continued
string"
echo "other"

预期输出:

echo "continued"$'\n'"string";echo "other"

输入

cat file1 \
file2 \
file3

预期输出:

cat file1 file2 file3

输入

for f in `pwd`/*
do
{ echo A; echo B
echo C; echo D; }
done

预期输出:

for f in `pwd`/*; do { echo A; echo B; echo C; echo D; }; done

等等。显然我不能只是

preg_replace('/[\r\n]+/', ';', $input);

因为 shell 支持复合命令和命令列表、多行字符串、多行命令连续运算符 ('\') 等等。似乎我别无他法,只能对输入命令进行标记并从那里开始。我的 bash 知识很一般,所以可能有些情况我错过了,它们也需要由解决方案来处理。

是否有现有的 PHP 库或包(我搜索了 packageagist 无济于事)可以帮助我更接近我的目标?如果不是,您将如何应对这一挑战(无需编写代码,只需将手指指向正确的方向)。

作为一个绝望的后备方案,我不得不求助于移植 bash 源代码本身,但我真的希望有人能提出一个捷径。

【问题讨论】:

  • 有趣的项目。您能否阐明将脚本打包成一行的动机。您可以对新行进行编码,并在将其发送到 bash 执行时对其进行解码吗?
  • @dash-o 我实际上是将命令发送到由 phpseclib 创建的交互式 shell。命令写入流后,我读取返回的数据包,等待命令提示符。如果我在多行上发送多个命令,则响应很可能包含多个提示(每个输入命令一个),并且我冒着不了解何时可以安全地继续交互的风险。但是,如果我在一行中发送多个命令 (cmd1;cmd2;cmd3),我可以放心地期待只有一个提示,一旦我检测到它,我的程序就可以继续。
  • 如果命令为国王的原因是通过检测提升来确定命令何时完成,请考虑附加,考虑按原样发送命令,然后添加“echo EEENNNDDD”。您的代码可以等待 EEENNNDDD 检测到执行结束。
  • 好主意,谢谢。我会将其添加到我要考虑的选项集中!

标签: php bash shell tokenize


【解决方案1】:

尝试为 bash 创建解析器是一个非常雄心勃勃(且模棱两可)的项目。 Bash 不断发展,在某些领域,将边界推到了 POSIX 标准之外。考虑缩小项目 - 可能针对 Posix shell(它将涵盖许多 shell 变体:dash、ash、...)。

考虑以https://pubs.opengroup.org/onlinepubs/9699919799/ 开头,它标识了几个引用选项。如果你仔细实施这些,你的方法(用';'替换行尾可能会奏效)。

另一种选择是从 bash 语法荧光笔开始,例如 vim 荧光笔。 (/usr/share/vim/vimNN/syntax/sh.vim,其中NN是vim版本)。

【讨论】:

  • 谢谢。我一定会阅读“Shell 命令语言”一章,因为它对我的目的很有用。至于vim语法高亮,我的只包含“llvm”、“nginx”和“tablegen”文件,但感谢指导,如果强迫我会搜索sh高亮。
猜你喜欢
  • 2016-01-08
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-03
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多