web-dev-qa-db-ja.com

別のコマンドの単一引用符と二重引用符を含むコマンドをラップする

私は最近 watch について学びましたが、比較的洗練されたコマンドで動作させるのに苦労しています。

たとえば、watchに3秒ごとにzshで次のコマンドを実行するように依頼します*

for x in `command_1 | grep keyword | cut -d' ' -f1`; do command_2 "Word[word=number]" $x; done

上記の行を見るとわかるように、他の特殊文字の中に、単一引用符、二重引用符が含まれています。

だから私は試した:

watch -n 3 "for x in `my_command | grep keyword | cut -d' ' -f1`; do command2 "rusage[mem=7000]" $x; done"

しかし、私は得ました:

!@#$#....;でxに一致するものが見つかりませんでした。終わった

他の組み合わせを試したが成功しなかった。これらの試みの1つを次に示します。

watch -n 3 "for x in $(bjobs -w | grep pre_seg | cut -d' ' -f1); do bmod -R "rusage[mem=7000]" $x; done"

これも同様のエラーになります。

これを機能させる方法はありますか?


*bashで機能するソリューションにも興味があります。

10

一般的なヒント:ネストのレベルが2つある場合は、内側のコマンドで単一引用符を使用しないでください。外側のコマンドは単一引用符で囲んでください。

追加のヒント:バックティックを使用しないでください-_`…`_-コードを実行する代わりに、その周りに$(…)を使用します。ドル括弧は、ネストされた引用符に関しては、ほとんどDWIM( 'Do what me平均')です。バッククォートには難解なシェル依存のルールがあります。

_watch -n 3 'for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'
_

単一引用符で囲まれたコマンド内で単一引用符が必要な場合は、_'\''_を使用できます。これらの4つの文字は、一重引用符内で一重引用符を引用する方法と考えてください。ただし、技術的には、これは一重引用符で囲まれた文字列を終了し、リテラル一重引用符を追加し、新しい一重引用符で囲まれた文字列を開始します(引き続き現在の単語)。

より複雑なケースでは、クオートを数えるか、一時変数を定義します。

_cmd='for x in $(my_command | grep keyword | cut -d" " -f1); do command2 "rusage[mem=7000]" "$x"; done'
watch_cmd='watch -n 3 "$cmd"'
_

この回答はzshに固有のものではありません。 Zshはここでは重要なことは何もしません。コマンド置換を二重引用符で囲む必要がないため、引用符を少し節約できます。引用符の必要性を減らす外部コマンドではなく組み込みコマンドを使用する方法がある場合もありますが、根本的な問題は他のシェルと同じです。

ああ、ところで、watchはzshではなくshでコマンドを実行することに注意してください。 zshでコマンドを実行する場合は、次を実行する必要があります

_watch -n 3 -x zsh -c "$cmd"
_

debian/Ubuntu、および

_export cmd
watch -n 3 'exec zsh -c "$cmd"'
_

(さらに引用!)他の場所。