web-dev-qa-db-ja.com

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

Stdout(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}
140
Paul

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_)で始まり、その後に任意の2文字(_.._)が続き、その後に0個以上の数字が続き、その後に_%_が続き、残りのテキスト(_.*_)
  • 置換の_\1_は、\(...\)内にキャプチャされた最初の式の内容を意味するため、この場合は_%_記号の前の数字
  • sedコマンドの_-n_フラグは、デフォルトでは行を印刷しないことを意味します。 _s///_コマンドの最後のpは、置換があった場合に行を出力することを意味します。つまり、コマンドは一致があった場合にのみ何かを出力します。
159
janos

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

command1 | xargs -I{} command2 {}

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

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

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

_command1_の出力をシミュレートするには、次のエコーステートメントを使用しています。

_$ 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 "
_
5
user56452

greppcre を使用してこれを試してください:

command | grep -oP '\$>\s+rate\s+\(\K[^\)]+'
4
Gilles Quenot

最初のタスクは、そのラインからレートを抽出することです。 GNU grep(非組み込みLinuxまたはCygwin)の場合、_-o_オプションを使用できます。必要な部分は、数字のみを含み、その後に_%_記号。_%_自体を抽出しない場合は、追加のトリックが必要です:a zero-width lookahead assertion 、これは何にも一致しませんが、何も従わない場合のみ_%_による。

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

別の可能性は、sedを使用することです。 sedの行の一部を抽出するには、sコマンドを使用して、行全体(_^_で始まり__$_で終わる)に一致する正規表現を、グループに保持する(\(…\))。保持するグループの内容で行全体を置き換えます。一般に、_-n_オプションを渡してデフォルトの印刷をオフにし、p修飾子を入れて、抽出するものがある行を印刷します(ここでは1行なので問題ではありません)。より多くの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_への引数として渡すことです。そのためのツールは command susbtitution です。 $(…)(ドル括弧)内にコマンドを配置すると、その出力がコマンドラインに代入されます。コマンドの出力は、空白スペースブロックごとに個別の単語に分割され、各単語はワイルドカードパターンとして扱われます。これを実行したくない場合は、コマンド置換を二重引用符で囲んでください:"$(…)"。二重引用符を使用すると、コマンドの出力が単一のパラメーターとして直接使用されます(唯一の変換は、出力の最後の改行が削除されることです)。

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

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

procstat -r `pgrep -x foo`

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

2
Vishal Sahu

grepを使用できます。これはPCRE-Perl互換の正規表現です。これにより、後読みを使用して、grepするときに結果に文字列「rate」を含めずに、rateの値に一致させることができます。

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

細部

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

  • _-o_は、括弧内の数字である_\d+_が検索するものだけを返します。
  • _-P_はgrepのPCRE機能を有効にします
  • _(?<=^rate \()_は、「rate(」で始まる文字列のみを返します

コマンド2

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

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

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

_$ command2 -t=${rate}
_

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

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

これは$(..)実行ブロック内でcommand1を実行し、その結果を取得してcommand2の_-t=.._スイッチに含めます。

1
slm