source
(別名.
)ユーティリティをよく知っています。このユーティリティは、ファイルからコンテンツを取得し、現在のシェル内で実行します。
今、私は次のようにいくつかのテキストをシェルコマンドに変換してから実行しています:
$ ls | sed ... | sh
ls
は単なるランダムな例であり、元のテキストは何でもかまいません。 sed
も、テキストを変換するための単なる例です。興味深いのはsh
です。 sh
に送ったものは何でもパイプして実行します。
私の問題は、新しいサブシェルを開始することを意味します。現在のシェル内でコマンドを実行したいです。テキストファイルにコマンドがある場合、source some-file
でできるようになります。
一時ファイルを作成したくないのは、汚いからです。
または、現在のシェルとまったく同じ特性でサブシェルを起動したいと思います。
バックティックを使用したソリューションは確かに機能しますが、出力を確認して変更しているときに頻繁にこれを行う必要があるため、結果を最終的に何かにパイプする方法があればはるかに好まれます。
ああ、/dev/stdin
の物はとてもきれいに見えましたが、より複雑なケースでは機能しませんでした。
だから、私はこれを持っています:
find . -type f -iname '*.doc' | ack -v '\.doc$' | Perl -pe 's/^((.*)\.doc)$/git mv -f $1 $2.doc/i' | source /dev/stdin
これにより、すべての.doc
ファイルの拡張子が小文字になります。
ちなみに、これはxargs
で処理できますが、それは重要ではありません。
find . -type f -iname '*.doc' | ack -v '\.doc$' | Perl -pe 's/^((.*)\.doc)$/$1 $2.doc/i' | xargs -L1 git mv
したがって、前者を実行するとすぐに終了し、何も起こりません。
$ ls | sed ... | source /dev/stdin
UPDATE:これは、bash 4.0、tcsh、およびダッシュで動作します(source
を.
に変更した場合) 。どうやらこれはbash 3.2ではバグがあったようです。 bash 4.0リリースノート から:
`。 'の原因となったバグを修正しましたデバイスや名前付きパイプなどの非正規ファイルからのコマンドの読み取りと実行に失敗する。
eval
コマンドは、まさにこの目的のために存在しています。
eval "$( ls | sed... )"
bash manual からの詳細:
eval
eval [arguments]
引数は単一のコマンドに連結され、その後読み取られて実行され、その終了ステータスがevalの終了ステータスとして返されます。引数がない場合、または空の引数のみがある場合、戻りステータスはゼロです。
うわー、これは古い質問であることは知っていますが、最近、まったく同じ問題を抱えていることに気付きました(これが私がここに来た理由です)。
とにかく-私はsource /dev/stdin
答えますが、私はより良いものを見つけたと思います。実際には一見シンプルです:
echo ls -la | xargs xargs
いいですね実際には、複数の行がある場合、各コマンドを個別に実行するのではなく、それらを単一のコマンドに連結するため、これはまだ必要なことを行いません。だから私が見つけた解決策は次のとおりです:
ls | ... | xargs -L 1 xargs
-L 1
オプションは、コマンド実行ごとに(最大)1行を使用することを意味します。 注:行の末尾がスペースの場合、次の行と連結されます!そのため、各行がスペース以外で終わっていることを確認してください。
最後に、あなたができる
ls | ... | xargs -L 1 xargs -t
実行されるコマンドを確認します(-tは冗長です)。
誰かがこれを読んでくれることを願っています!
process substitution を使用してみてください。これは、コマンドの出力を一時ファイルに置き換えた後、そのファイルを取得できます。
source <(echo id)
これは質問に対する「正しい答え」だと思います。
ls | sed ... | while read line; do $line; done
つまり、while
ループにパイプできます。 read
コマンドコマンドは、そのstdin
から1行を取得し、変数$line
に割り当てます。 $line
は、ループ内で実行されるコマンドになります。そして、入力にさらに行がなくなるまで続けます。
これは、一部の制御構造(別のループなど)ではまだ機能しませんが、この場合の法案に適合します。
`ls | sed ...`
ls | sed ... | source -
はきれいになりますが、残念ながらsource
は-
はstdin
を意味します。
あなたの解決策は、逆ティックを使用したコマンド置換であると思います: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html
セクション3.4.5を参照してください
Bash 3.2(macos)でmark4oのソリューションを使用するには、この例のようなパイプラインの代わりにhere文字列を使用できます。
. /dev/stdin <<< "$(grep '^alias' ~/.profile)"
なぜsource
を使用しないのですか?
$ ls | sed ... > out.sh ; source out.sh