パイプコマンドで使用される eval

パイプコマンドで使用される eval

コマンドが1行で保存されたfile.txtがあり(このコマンドはコンソールで実行するときに有効です)、shを使用して1行で実行したいとします。

cat file.txt | eval

何が足りないのでしょうか?何かヒントはありますか?

では、多くのコマンド (各行に 1 つずつ) を含むファイルがあり、1 つのコマンド (1 行全体) のみを実行したい場合はどうすればよいでしょうか? 私の最初のアイデアは次のとおりです。

head -n5 | tail -n1 | eval

答え1

evalコマンド文字列をstdinから読み取りません。

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)"

コマンドがファイル内にある場合は、の代わりにstandardまたは/ /evalを使用できます。.bashzshksh source

source ./file

( を追加することが重要であることに注意してください./。そうでない場合、 は現在のディレクトリのを考慮する前にで をsource検索します。POSIX モードの場合、で見つからない場合でも、現在のディレクトリの を考慮しません)。file$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 コマンドをネストする難しさを考えると$(...)、まさにあなたが尋ねていることを実行できるのはうれしいことです。

を使用する代わりにevalawkまたはperlのシステム コマンドを使用します。

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

(これは古い質問だとは思います。)

関連情報