Bashで複数行のコマンド出力を解析する方法は?

Bashで複数行のコマンド出力を解析する方法は?

以下を出力するコマンドがあります。

Some text here
    1,3456: "Descr 1"
    2,7891: "Descr 2"
    3,0976: "Descr 3"

Some other random text here

最初の列を解析して値をどこかに保存して、エンドユーザーにオプションを提供できるbashスクリプトを作成したいと思います。

awkを使用して最初の列を取得することはできますが、最後のランダムなテキスト(「ここに別のランダムなテキストがあります」)のため、awkコマンドはめちゃくちゃになります。

これが私が今まで持っているものです:

#!/bin/bash

VERSIONS=`/usr/libexec/somebin -V`

OPTIONS=$VERSIONS | awk -F'[,]' '{print $1}'

while read -r line; do
   echo "... $line ..."
done <<< $OPTIONS

それがすることは印刷するだけです:

Some text here
    1,3456: "Descr 1"
    2,7891: "Descr 2"
    3,0976: "Descr 3"

...  ...

でも印刷したいです。

1
2
3

答え1

パイプ前の簡単なコマンド:

OPTIONS=$VERSIONS | awk -F'[,]' '{print $1}'

OPTIONSに設定します$VERSIONS。実際のユーティリティ名がないため、コマンドは単なる割り当てであるため、出力は生成されません。したがって、何もパイプで接続されていないため、awk何もawkしません。 (何かをしてはいけない$OPTIONS

悪いことに、パイプは前後のコマンドがサブシェルで実行されることを保証します。したがって、OPTIONS複合コマンドを含むシェルには設定されません。

私はあなたが望むものは次のように思う。

OPTIONS=$(/usr/libexec/somebin -V | cut -f1 -d,)

または多分

VERSIONS=$(/usr/libexec/somebin -V)
OPTIONS=$(echo "$VERSIONS" | cut -f1 -d,)

ここで、cutコマンドは呼び出したのと同じ操作を実行しますawk

ただし、awk コマンドまたは awk コマンドの両方が「特定のテキスト」を含む行をフィルタリングしないため、次の実際のフィルタが必要になる場合があります。

VERSIONS=$(/usr/libexec/somebin -V | grep ,)
OPTIONS=$(echo "$VERSIONS" | cut -f1 -d,)

答え2

awk -F'[,]' '/^[ ]/{print $1}'

空白で始まる行でのみ機能し、空白のない行はスキップされます。別のオプションは、カンマを含む行を見つけるか、スペースの代わりに巧妙なタブを使用している場合は別の正規表現を見つけることです。

答え3

bashのみを使用してこれを実行できます。

IFS=","; while read -r a b; do [[ $a =~ [0-9]+ ]] && echo $a; done < 1; unset IFS
1
2
3

関連情報