$variableから|パイプ文字を使用すると、bashは他のパラメータとして扱われます。これをエスケープする方法は?

$variableから|パイプ文字を使用すると、bashは他のパラメータとして扱われます。これをエスケープする方法は?

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

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

しかし、エラーが発生します。

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

"| sort -n"内容を に渡されたパラメータとして扱うようですls

通常のパイプコマンドのように処理されるようにどのようにエスケープしますか?

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

答え1

|あなたは正しいです、そうしないでください。その理由は、シェルが変数置換を実行する前に、すでにパイプを見つけてコマンドに分割するためです。したがって、|それは別のキャラクターと見なされます。

考えられる解決策の1つは、パイプ文字を文字通り配置することです。

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

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

$ cmd=cat
$ ls | $cmd

この方法は評価の微妙さ。また、見ることができますここ

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

より洗練されたアプローチは、bash通常の文字列の代わりに配列を使用することです。

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

cmd引用符付き引数を含むコマンドが必要な場合は、配列の利点が重要になります。

答え2

eval次のコマンドを使用できます。

eval "ls $pipedargument"

または、次のように関数を定義する方が良いでしょう。

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

次に、必須パラメータを使用して呼び出します。

sorted ls /tmp

答え3

私はこれに関数を使用します。それは次のとおりです。

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

関連情報