使用 Heredoc 迭代命令列表

使用 Heredoc 迭代命令列表

这工作正常:

$ eval 'echo "1" > ~/Desktop/in/foo'

但不是这个:

$ while IFS= read _cmd; do eval "$_cmd"; done < <(cat << EOF
'echo "1" > ~/Desktop/in/foo'
'echo "2" > ~/Desktop/in/bar'
EOF
)
bash: echo "1" > ~/Desktop/in/foo: No such file or directory
bash: echo "2" > ~/Desktop/in/bar: No such file or directory

如何修复它?


更新

正如所建议的,删除单引号是可行的,但不适用于此变体(仅用单引号引起来的文件名也是如此):

$ while IFS= read _cmd; do eval "$_cmd"; done < <(cat << EOF 
echo "1" > ~/Desktop/in/foo (bis)
echo "2" > ~/Desktop/in/bar
EOF
)

连同提供的解决方案:

"$SHELL" << EOF
echo "1" > ~/Desktop/in/'foo (bis)'
echo "2" > ~/Desktop/in/bar
EOF

答案1

当您运行 时eval 'echo "1" > ~/Desktop/in/foo',shell 会删除单引号,然后eval计算echo "1" > ~/Desktop/in/foo

当您运行eval "$_cmd"(在更新前的代码中)时,shell 会展开$_cmd并删除双引号,然后eval计算'echo "1" > ~/Desktop/in/foo'.请注意单引号。您不想eval看到它们,请将它们从此处的文档中删除。

在更新后的代码中,您可能想要eval评估echo "1" > ~/Desktop/in/'foo (bis)',因此请使用此处文档中的这一行。


嗯,“精确”一般来说并不是正确的词。一般来说<< EOF(与 例如 相对<< 'EOF')扩展了此处文档中的变量和其他一些内容(您的示例中没有,但一般来说这就是它的工作原理)。那么IFS= read _cmd不是IFS= read -r _cmd。最后eval得到一个字符串,不一定是精确的你使用的字符串。

逐行评估使得评估多行命令变得不可能。

除非您真的想依赖您提供的字符串<< EOFIFS= read对其执行什么操作(并且您知道自己在做什么),否则只需直接在脚本中编写代码即可。毕竟,您希望 shell 解释脚本来计算echo "1" > ~/Desktop/in/foo.甚至您不需要其他 shell 进程。这里不需要这里的文档。

我猜想另一个 shell 进程的预处理代码可能有意义(在某些情况下并且当你小心的时候),但是你应该使用 eg bash << EOF,而不是read.


另一件事:代码片段done < <(cat << EOF可以简化为done << EOF(请注意,此更改需要)从代码末尾删除 )。

相关内容