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 字符串,其中单引号禁用参数替换,因此我们可以输入文字文本。(无评估)。然后我们通过 <<EOF2
和 EOF2
.
创建的另一个 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 的文档。
我在 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 字符串,其中单引号禁用参数替换,因此我们可以输入文字文本。(无评估)。然后我们通过 <<EOF2
和 EOF2
.
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 的文档。