eval 与管道命令一起使用

eval 与管道命令一起使用

我有 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// zshksh source

source ./file

(请注意,添加 很重要./。否则,在考虑当前目录中的之前先source查找filein 。如果在 POSIX 模式下,甚至不会考虑当前目录中的 ,即使在 中 没有找到)。$PATHfilebashfile$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,只需使用awkorperl的系统命令:

// 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

(我意识到这是一个老问题。)

相关内容