![eval 与管道命令一起使用](https://linux22.com/image/38527/eval%20%E4%B8%8E%E7%AE%A1%E9%81%93%E5%91%BD%E4%BB%A4%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8.png)
我有 file.txt ,命令存储在一行中(该命令在控制台中运行时有效),我想用 sh 在一行中执行它
cat file.txt | eval
缺什么?有什么建议吗?
如果我的文件包含许多命令(每行一个)并且我只想执行一个命令(一整行)怎么办?我的第一个想法是:
head -n5 | tail -n1 | eval
答案1
eval
不从标准输入读取其命令字符串。
eval "$(cat file.txt)"
# or easier, in ksh/bash/zsh
eval "$(<file.txt)"
# usually you cannot be sure that a command ends at the end of line 5
eval "$(head -n 5 file.txt)"
相反,如果命令位于文件中,则eval
可以使用标准.
或bash
// zsh
:ksh
source
source ./file
(请注意,添加 很重要./
。否则,在考虑当前目录中的之前先source
查找file
in 。如果在 POSIX 模式下,甚至不会考虑当前目录中的 ,即使在 中 没有找到)。$PATH
file
bash
file
$PATH
当然,这不适用于选择文件的一部分。这可以通过以下方式完成:
head -n 5 file.txt >commands.tmp
source ./commands.tmp
或者(使用 ksh93、zsh、bash):
source <(head -n 5 file.txt)
答案2
所以...你的问题的解决方案是 100% 可能的,并且(在 的背景下make
)很重要。
我用 makefile 遇到了这个问题,考虑到在已经用于调用变量的 makefile 中嵌套 bash 命令的困难$(...)
,能够准确地执行您所要求的操作是很好的。
不使用eval
,只需使用awk
orperl
的系统命令:
// command_list.sh:
echo "1"
echo "2"
echo "3"
// command line prompt:
$: cat command_list.sh | awk '{system($0)}'
1
2
3
并且,指挥大楼:
// a readable version--rather than building up an awk miniprogram,
// split into logical blocks:
$: cat inputs.txt | awk '{print "building "$1" command "$2" here "}' | awk '{system($0)}'
答案3
从技术上讲,如果您想从管道中读取某些内容,则不可能评估当前环境中的某些内容,因为管道中的每个命令都作为单独的进程执行。
但是,根据您想要实现的目标,这可能并不重要。无论如何,这里是eval
针对管道的内容运行的:
❯ echo echo hi | eval "$(cat -)"
hi
这是一个捕获的例子。类似下面的内容不会打印1
:
❯ echo a=1 | eval "$(cat -)"; echo $a
我们必须执行以下操作:
❯ echo a=1 | { eval "$(cat -)"; echo $a; }
1
答案4
如果您不确定使用eval
,请使用sh
:
cat file.txt | sh
是的,它将在单独的 sh 实例中运行,但这一事实是自我记录的。
还有while read
:
cat file.txt | while read cmd; do eval $cmd; done
执行file.txt第5行命令:
sed -n 5p file.txt | sh
(我意识到这是一个老问题。)