選択はあなた次第です。$@
値を引用しない場合、追加の展開と解釈が行われます。引用すると、関数に渡されたすべての引数がそのまま展開されます。&>|
とにかく自分自身で引数を解析することなく、などのようなシェル構文トークンを確実に処理することは決してできません-したがって、次のいずれかの関数を渡すより合理的な選択肢が残ります:
- を使用した単一の単純なコマンドの実行で使用される正確な単語
"$@"
。
...または...
- 引数をさらに展開および解釈したバージョン。これは、と一緒に単純なコマンドとして一緒に適用されるだけ
$@
です。
意図的であり、選択したものの効果が十分に理解されている場合、どちらの方法も間違っていません。どちらの方法にも利点がありますが、2番目の方法の利点が特に役立つことはほとんどありません。それでも...
(run_this(){ $@; }; IFS=@ run_this 'ls@-dl@/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
...そうではありません役に立たない、ただまれそうなくらいであるように使用。また、bash
シェルでは、特別なビルトインのコマンドラインまたは関数の前に定義が追加されてbash
いても、デフォルトでは変数定義を環境に固定しないため、グローバル値$IFS
は影響を受けず、その宣言はローカルですrun_this()
呼び出しのみ。
同様に:
(run_this(){ $@; }; set -f; run_this ls -l \*)
ls: cannot access *: No such file or directory
...グロビングも構成可能です。引用符は目的に役立ちます-それらは無料です。それらがなければ、シェル拡張は追加の解釈を受けます - 設定可能な解釈。以前は-非常に古いシェルで- 展開だけでなく、すべての入力$IFS
にグローバルに適用されていました。実際、シェルrun_this()
はの値ですべての入力語を壊したという点で非常によく似た動作をします$IFS
。したがって、探しているのが非常に古いシェルの動作である場合は、を使用する必要がありますrun_this()
。
私はそれを探しているわけではありません。そして、現時点で有用な例を見つけるのにかなり苦労しています。一般的に、シェルで実行するコマンドは、入力するコマンドを好む。ですから、選択肢があれば、私はほとんどいつもそうしrun_that()
ます。それ以外で...
(run_that(){ "$@"; }; IFS=l run_that 'ls' '-ld' '/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
ほぼ何でも引用できます。コマンドは引用符付きで実行されます。コマンドが実際に実行されるまでに、すべての入力語はすでに引用除去を行っているため、これが機能します。これはシェルの入力解釈プロセスの最後の段階です。違いはそう'ls'
とls
問題だけシェルが解釈されることができますが-と引用理由ですls
どんなことを保証し、エイリアスの名前がls
私の引用されたために置換されていないls
コマンドワードを。それ以外に、引用符が影響するのは、単語の区切り(変数/入力空白の引用符が機能する方法と理由)と、メタ文字と予約語の解釈だけです。
そう:
'for' f in ...
do :
done
bash: for: command not found
bash: do: unexpected token 'do'
bash: do: unexpected token 'done'
run_this()
またはのいずれかでそれを行うことはできませんrun_that()
。
しかし、関数名、または$PATH
「dコマンド、または組み込みコマンドがうまく引用したり引用符で囲まれていない実行され、それは正確にどのようにだrun_this()
とrun_that()
最初の場所での作業。$<>|&(){}
これらのいずれでも有用なことはできません。の略eval
です。
(run_that(){ "$@"; }; run_that eval printf '"%s\n"' '"$@"')
eval
printf
"%s\n"
"$@"
しかし、それがないと、使用する引用符によって単純なコマンドの制限に制限されます($@
コマンドがメタ文字を解析するときにプロセスの開始時に引用符のように振る舞わないため)。同じ制約は、コマンドラインの割り当てとリダイレクトにも当てはまりますが、これらは関数のコマンドラインに限定されます。しかし、それは大したことではありません:
(run_that(){ "$@";}; echo hey | run_that cat)
hey
パイプを開いたときと同じくらい簡単に<
入力または>
出力をリダイレクトできます。
とにかく、回り道で、ここには正しい方法も間違った方法もありません-それぞれの方法には用途があります。使用するつもりで書いて、あなたが何をするつもりなのかを知っておくべきです。引用符を省略することには目的があります -そうでなければ、引用符はまったくありません-しかし、目的に関係のない理由で引用符を省略すると、単に悪いコードを書いていることになります。あなたが意味することをしてください。とにかくやってみます。
run_that
の動作は間違いなく私が期待するものです(コマンドへのパスにスペースがある場合はどうなりますか?)。他の動作が必要な場合は、コールサイトでデータの内容を知っている場所で引用符を外してください。この関数をとして呼び出すことを期待しますがrun_that ls -l
、どちらのバージョンでも同じように機能します。違った期待をした事例はありますか?