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