|の使用 $ variableからのパイプ文字は、それをbashの別の引数として扱います。それを脱出する方法?


8

私はこのようなbashスクリプトを持っています

export pipedargument="| sort -n"
ls $pipedargument

しかし、それはエラーを与えます

ls: |: No such file or directory
ls: sort: No such file or directory

"| sort -n"渡された引数としての内容を扱っているようlsです。

通常のパイプコマンドとして扱われるように、どうすればエスケープできますか?

条件付きでを設定しようとしています$pipedargument。私はコマンドの異なるバージョンを条件付きで実行することができると思いますが、これを上記のように機能させる方法があるかどうか疑問に思いますか?

回答:


9

あなたは|そのように使うことができないのは正しいです。その理由は、シェルが変数の置換を行う前に、パイプラインをすでに探してコマンドに分割しているためです。したがって、|は別の文字として扱われます。

考えられる1つの回避策は、パイプ文字を文字どおりに配置することです。

$ cmd="sort -n"
$ ls | $cmd

パイプラインがcat不要な場合は、「nop」またはプレースホルダーとして使用できます。

$ cmd=cat
$ ls | $cmd

このメソッドはeval微妙な点を回避します。こちらもご覧ください

より良いアプローチ:配列

より洗練されたアプローチではbash、プレーンな文字列の代わりに配列を使用します。

$ cmd=(sort -n)
$ ls | "${cmd[@]}"

cmd引用符で囲まれた引数を含むコマンドが必要になるとすぐに、配列の利点が重要になります。


引用符で囲まれた引数の場合に配列が必要な理由を明確にしていただけませんか?私はそれに遭遇しましたが、なぜそれが機能しないのかよくわかりません。
anxieux 2017年

@anxieux短い答えは、シェル文字列の内側にある引用符は、単語をグループ化する構文力をすべて失い、代わりに他の文字と同様に扱われるということです。この問題に関するより長く優れた説明については、「コマンドを変数に入れようとしていますが、複雑なケースは常に失敗します!」
John1024

5

eval次のコマンドを実行できます。

eval "ls $pipedargument"

または、次のような関数をより適切に定義します。

sorted() { "$@" | sort -n; }

その後、必要な引数を付けて呼び出します。

sorted ls /tmp

:別のオプションは、別名を定義することですalias ls='ls | sort -n'
thiagowfx

0

これには関数を使用します。何かのようなもの:

### usage pipedargument cmd args ###

pipedargument()
{
    sort -n <<< "$( "$@" )"
}

$ pipedargument /sbin/ifconfig eth0
      RX bytes:5904986765 (5.4 GiB)  TX bytes:714370767 (681.2 MiB)
      RX packets:5981427 errors:0 dropped:0 overruns:0 frame:0
      TX packets:4403989 errors:0 dropped:0 overruns:0 carrier:0
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      collisions:0 txqueuelen:1000 
      inet addr:XXX.XXX.X.XX  Bcast:XXX.XXX.X.XXX  Mask:255.255.255.0
      inet6 addr: xx00::0x0x:00xx:xx0:000/00 Scope:Link
eth0      Link encap:Ethernet  HWaddr 0x:0x:00:x0:00:00
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.