2017-04-10 8 views
1

システム管理者として、私は別のキーボードレイアウトの異なるサーバーで作業する必要があります。だから私は '&'、 '|'のようなキーを見つけることに大きな問題に直面するたびに。BASH:変数に特別なシンボルを割り当てる

これらのシンボルを変数に割り当てて、シンボルが必要なときに変数を呼び出す方法はありますか?

例えば:

echo "|" > filename 
pipe = $(cat filename) 

ps -ef somethinghere($(pipe)) grep java 

はjavaプロセスを実行している私を与える必要があるとします。私はできたが失敗したすべてを試した。

助けてください。

+1

キーボードレイアウトを変更する方が簡単ですか? – Derlin

+0

@Derlin no。同じロケールの他のユーザーが、同じユーザーの信用を使用している可能性があります。 –

+0

**データ**が**構文**として解析されていないため、これは動作しません。もしそうであれば、悪意のあるデータを処理しています(例えば '/ tmp/$(rm -rf $ HOME)'というファイル)ほとんど不可能だろう。 –

答えて

2

あなたが本当にことをしたい場合は、こちらの方法です:猫と

pipe="|" 
eval $(echo ps -ef $pipe grep java) 

eval $(echo ps -ef $(cat pipe.txt) grep java) 

evalを使用することは推奨されていることと、このコマンドは、できるだけ早く問題になること引用符、エスケープシーケンス、ファイル名、および/またはスペースを含む引数を含む複雑なコマンドが必要です。

私の意見では、さまざまなLinuxシステムでキーボードレイアウトを変更する方法を教えてください(たとえばloadkeysを参照)。

+1

これは非常に限られた状況で機能します。スペースでファイル名を扱います。引用符を必要とするコマンド。それはすぐに分解されるでしょう。 –

+0

...少し問題の少ない変種として、 'eval" ps -ef $ pipe grep java "はそれが何をしているか(コードとして評価される単一の文字列を生成する)について少なくとも*明示的*であり、 (つまり、より多くの単語を追加する場合には 'eval" ps -ef $ pipe grep \ "java -Xmx \" "'などの構文上の引用符ではなくリテラルを使用する必要があります)。 –

3

次の関数は、仕事をする:より良い何

# read a number of arguments on the left-hand side; those actual arguments; then the RHS 
pipe() { 
    local nargs 
    local -a firstCmd 

    nargs=$1; shift 
    firstCmd=() 
    for ((i=0; i<nargs; i++)); do 
    firstCmd+=("$1"); shift 
    done 
    "${firstCmd[@]}" | "[email protected]" 
} 

# basic use case 
pipe 3 ps -ef somethinghere grep java 

# or, for a pipeline with more than two components: 
pipe 3 ps -ef somethinghere pipe 2 grep java tee log.txt 

evalを用いて、溶液とは異なり、それがさらに複雑な値でうまくいくということです。

pipe 3 ps -ef 'something with spaces here' grep java 

一つは、可能性がありまた、sigil値を使用するこの関数のバージョンを記述してください:

pipe() { 
    local sigil 
    local -a firstCmd 

    sigil=$1; shift 
    firstCmd=() 
    while (($#)); do 
    if [[ $1 = "$sigil" ]]; then 
     shift 
     "${firstCmd[@]}" | pipe "$sigil" "[email protected]" 
     return 
    else 
     firstCmd+=("$1") 
     shift 
    fi 
    done 
    "${firstCmd[@]}" 
} 
この場合、

、あなたも行うことができます:

sigil=$(uuidgen) # generate a random, per-session value 
pipe "$sigil" ps -ef 'something with spaces here' "$sigil" grep java "$sigil" tee log.txt 
+0

'pipe(){" $ {@:2:$ 1} "のようなonlinerとしてソリューションを実装する際に問題が発生していますか? "$ {@:$(($ 1 + 2))}"; } '?私はこれがあなたの最初の提案された解決策と同等であると思います。おそらく少しわかりにくいかもしれません... – Fred

+0

確かに、私はむしろ冗長で読みやすいコードです。要約版を別の回答として提供したい場合は、無料でご利用ください。 –

1

ビル同じロジックでCharlesDuffyによって提案された最初のソリューションとして、これは同等でなければなりません:

pipe() 
{ 
    "${@:2:$1}" | "${@:$(($1+2))}" 
} 

よりもむしろ構築するために反復を使用して残りのコマンドが第2のコマンドのみを含むまで、最初のコマンドとシフト引数を持つ配列です。このソリューションは拡張を使用します。

  • "${@:2:$1}"

    は2
  • "${@:$(($1+2))}"は両方のケースでは、位置$1 + 2

で始まるすべての引数を展開した位置から、$1議論を展開し、二重引用符は、引数は、引数ごとに一つの単語として展開することを確認します(単語の分割は行われません)。

これがあまりにもわかりにくい場合は、コードを維持しなければならない予定のコーダーへの可読性が何らかの利点を勝ち得る可能性があるため、避けてください。

関連する問題