私はこのような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つは、パイプ文字を文字どおりに配置することです。
$ cmd="sort -n"
$ ls | $cmd
パイプラインが不要な場合は、cat
を「nop」またはプレースホルダーとして使用できます。
$ cmd=cat
$ ls | $cmd
このメソッドは evalの機微 を回避します。 here も参照してください。
より洗練されたアプローチでは、プレーンな文字列の代わりにbash
配列を使用します。
$ cmd=(sort -n)
$ ls | "${cmd[@]}"
コマンドcmd
に引用符付きの引数を含める必要があるとすぐに、配列の利点が重要になります。
コマンドをeval
uateできます:
eval "ls $pipedargument"
または、次のような関数をより適切に定義します。
sorted() { "$@" | sort -n; }
その後、必要な引数を付けて呼び出します。
sorted ls /tmp
これには関数を使用します。何かのようなもの:
### 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