Shell heredoc 里面 php heredoc

Shell heredoc inside php heredoc

我在 php 脚本中有类似的内容:

<?php
...
function log() {
    // saving the log into a file.
    exec(<<<BASH
cat >> $logFile <<EOF
$log
EOF
BASH
    );
}
...

如您所见,两个 heredocs(BASH 是 php 和 EOF 是 shell)以人们认为正确的方式结束,但是当我阅读日志时创建了日志有这样的东西:

...
my logged string of an important event
EOF
my logged string of another important event
EOF
...

我检查了 apache 日志,它有以下条目:

sh: line 1: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')

我做错了什么?

拜托,我知道还有许多其他实现,例如使用 php 函数或使用引号代替 heredocs。但我很好奇为什么在这种特殊情况下这不起作用。

编辑。 我澄清了代码,所以更清楚我在谈论 php 运行 shell 命令。

PHP 案例的更新答案

假设我们有 test.php 包含以下内容的文件:

<?php
function mylog() {
  $logFile = 'test.log';
  $log = 'test';

  exec(<<<BASH
cat >> $logFile <<EOF
$log
EOF
BASH
     );
}

mylog();

然后 php test.php 产生正确的东西 (!):

rm -f test.log
php test.php
cat test.log

输出:

test

现在让我们缩进 Bash 部分:

<?php
function mylog() {
  $logFile = 'test.log';
  $log = 'test';

  exec(<<<BASH
  cat >> $logFile <<EOF
  $log
  EOF
BASH
     );
}

mylog();

现在 php test.php 生成的内容与您在 问题:

rm -f test.log
php test.php
cat test.log

输出:

sh: line 2: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')
  test
  EOF

显然,您的 Bash 部分缩进了,这是无效的 Bash 语法。所以你只需要删除 Bash 部分的缩进。至少,EOF 不应该缩进。

我认为 OP 意味着纯 Bash

的原始答案

exec 执行命令,但您需要计算 bash 表达式。所以你需要 eval 来代替。

要使用 eval 构造命令,请使用以下命令:

eval "$(
cat <<'EOF'

cat >> test.log <<EOF2
log contents
EOF2

EOF
)"

所以我们用"$()"构造了一个Bash变量。在变量中,我们使用 cat <<'EOF'EOF 创建了一个 here-doc 字符串,其中单引号禁用参数替换,因此我们可以输入文字文本。(无评估)。然后我们通过 <<EOF2EOF2.

创建的另一个 here-doc 字符串编写了 log contents

我们可能会保存 Bash 变量,然后根据需要多次使用它:

cmd="$(
cat <<'EOF'

cat >> test.log <<EOF2
log contents
EOF2

EOF
)"

rm test.log
eval "$cmd"; eval "$cmd"; eval "$cmd"
cat test.log

输出:

log contents
log contents
log contents

请参阅 here documents 的文档。