前のコマンドの出力を引数としてnextに渡します


119

データを標準出力(command1 -p=aaa -v=bbb -i=4)に出力するコマンドがあります。出力行には次の値を設定できます。

rate (10%) - name: value - 10Kbps

その「レート」を保存するために、その出力をgrepしたいです(ここでパイプが役立つと思います)。そして最後に、そのレートを2番目のコマンドのパラメーターの値にしたいと思います(言いましょうcommand2 -t=${rate}

私の側には注意が必要です。パイプ、grep、sedなどの使用方法を詳しく知りたいと思います。

私はそのような組み合わせをたくさん試しましたが、私はこれらを混同しています:

$ command1 -p=aaa -v=bbb -i=4 | grep "rate" 2>&1 command2 -t="rate was "${rate}

回答:


144

2つの非常に異なるタイプの入力を混同しています。

  1. 標準入力(stdin
  2. コマンドライン引数

これらは異なり、さまざまな目的に役立ちます。一部のコマンドは、両方の方法で入力を受け取ることができますが、通常はそれらを異なる方法で使用します。たとえば、wc次のコマンドを使用します。

  1. 入力を渡すstdin

    ls | wc -l
    

    これにより、出力の行がカウントされます ls

  2. コマンドライン引数で入力を渡す:

    wc -l $(ls)
    

    これにより、印刷されるファイルのリストの行がカウントされますls

完全に異なるもの。

質問に答えるには、最初のコマンドの出力からレートを取得し、2番目のコマンドのコマンドライン引数としてレートを使用するように聞こえます。これを行う1つの方法を次に示します。

rate=$(command1 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p')
command2 -t "rate was $rate"

の説明sed

  • s/pattern/replacement/このコマンドは、いくつかのパターンを交換することです
  • パターンは、行が "rate"(^rate)で始まり、その後に任意の2文字(..)が続き、0桁以上が続き%、が続き、残りのテキスト(.*)が続くことを意味します。
  • \1置換では、内\(...\)でキャプチャされた最初の式の内容を意味するため、この場合は%符号の前の数字
  • コマンドの-nフラグは、sedデフォルトで行を印刷しないことを意味します。p最後のs///コマンドは、交換があった場合の行を印刷することを意味します。要するに、コマンドは一致した場合にのみ何かを出力します。

13

私はこれを使用する傾向があります:

command1 | xargs -I{} command2 {}

command1置換(中括弧)を使用してxargsの出力をに渡しますcommand2。command1がnullで終了する文字列findを使用-print0して追加-0することを確認し、見つかったものごとに呼び出します。xargsxargscommand2

あなたの場合(そして@Janosからsed行を取る):

command1 -p=aaa -v=bbb -i=4 | sed -ne 's/^rate..\([0-9]*\)%.*/\1/p' | xargs -I{} command2 -t="rate was {}"

これは物事をうまく保ち、パイプでつないだものです。
Mateen Ulhaq

4

command1私の出力をシミュレートするには、このechoステートメントを使用しています。

$ echo -e "Foo\nrate (10%) - name: value - 10Kbps\nBar"
$ alias command1='echo -e "Blah\nrate (10%) - name: value - 10Kbps\nBlag"'

簡単なテスト:

$ command1
Blah
rate (10%) - name: value - 10Kbps
Blag

それはすべて良いので、それを解析してみましょう:

$ command1 | grep 'rate'
rate (10%) - name: value - 10Kbps

目的の行を取得し、command1それをcommand2次のように渡します。

$ alias command2='echo'
$ command2 -t="rate was "$(command1 | grep 'rate')
-t=rate was rate (10%) - name: value - 10Kbps

私は"rate was "$(command1 | grep 'rate')自動的に連結することを期待しています。空白のためにそれが機能しない場合、代わりにそのように入力を渡すことができるはずです:

$ alias command2='echo'
$ command2 -t=$(echo '"rate was ' $(command1 | grep 'rate') '"')
-t="rate was rate (10%) - name: value - 10Kbps "


2

最初のタスクは、その行からレートを抽出することです。GNU grep(非組み込みLinuxまたはCygwin)を使用すると、-oオプションを使用できます。必要な部分は、数字のみを含む部分で、その後に%記号が続きます。%自身を抽出したくない場合は、追加のトリックが必要です。ゼロ幅の先読みアサーションは、何も後に続かない場合にのみ一致し%ます。

command1 -p=aaa -v=bbb -i=4 | grep -o -P '[0-9]+(?=%)'

別の可能性は、sedを使用することです。sedの行の一部を抽出するには、行s全体(で始まり、^で終わる$)に一致する正規表現を使用して、グループに保持する部分(\(…\))でコマンドを使用します。行全体を保持するグループのコンテンツで置き換えます。一般に、-nデフォルトの印刷をオフにするオプションを渡し、p抽出するものがある行を印刷するために修飾子を配置します(ここでは重要ではないので単一行があります)。より多くのsedトリックについて、一致するパターンの後の行の部分のみ返すおよび「sed」と一致する正規表現の抽出を参照してください。

command1 -p=aaa -v=bbb -i=4 | sed 's/^.*rate(\([0-9]*\)%).*$/\1/'

sedよりも柔軟性が高いのはawkです。Awkは、小さな命令型言語で各行の命令を実行します。ここでレートを抽出する方法は多数あります。2番目のフィールドを選択し(フィールドはデフォルトで空白文字で区切られています)、数字ではないすべての文字を削除します。

command1 -p=aaa -v=bbb -i=4 | awk '{gsub(/[^0-9]+/, "", $2); print $2}'

次のステップは、レートを抽出したので、引数としてに渡すことcommand2です。そのためのツールは、コマンドsusbtitutionです。コマンドを中に$(…)挿入すると(ドル括弧)、その出力はコマンドラインに置き換えられます。コマンドの出力は、各空白ブロックで個別の単語に分割され、各単語はワイルドカードパターンとして扱われます。これを実行したくない場合は、コマンド置換を二重引用符で囲みます"$(…)"。二重引用符を使用すると、コマンドの出力が単一のパラメーターとして直接使用されます(唯一の変換は、出力の最後の改行が削除されることです)。

command2 -t "$(command1 -p=aaa -v=bbb -i=4 |
               sed 's/^.*rate(\([0-9]*\)%).*$/\1/')"

0

使用できますgrep。PCRE-Perl Compatible Regular Expressionsです。これにより、grepを実行するときに結果に文字列 "rate"を含めることなく、後読みを使用してrateの値を一致させることができます。

$ echo "rate (10%) - name: value - 10Kbps" | grep -oP '(?<=^rate \()\d+'
10

詳細

上記grepは次のように機能します。

  • -o探しているもののみを返します。\d+これは、括弧内の数字です。
  • -P grepのPCRE機能を有効にします
  • (?<=^rate \() 「rate(」で始まる文字列のみを返します

command2

"rate"の値をキャッチするには、次のcommand1ように実行できます。

$ rate=$(command 1 | grep -oP '(?<=^rate \()\d+'

次に、2番目のコマンドでは、単にその変数を使用します。

$ command2 -t=${rate}

あなたは空想を得て、それをすべて1行にすることができます:

$ command2 -t=$(command1 | grep -oP '(?<=^rate \()\d+')

これにより、$(..)実行ブロック内でcommand1が実行され、その結果が取得されてcommand2の-t=..スイッチに含まれます。


0

通常、コマンドを使用して出力を別のコマンドの引数として配置します。たとえば、freebsdのプロセスfooによって消費されるリソースを見つけるには、次のようになります。

procstat -r `pgrep -x foo`

ここでは、pgrepを使用して、プロセスfooのPIDを抽出します。これは、引数としてプロセスのPIDを予期するprocstatコマンドに渡されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.