複数行のテキストでテキストを検索する

複数行のテキストでテキストを検索する

aplay -L複数のデバイスとその説明を一覧表示するために使用しています。

$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
pulse
    PulseAudio Sound Server
surround40:CARD=PCH,DEV=0
    HDA Intel PCH, ALC1220 Analog
    4.0 Surround output to Front and Rear speakers
hw:CARD=PCH,DEV=0
    HDA Intel PCH, ALC1220 Analog
    Direct hardware device without any conversions

ここでnullhw:CARD=PCH,DEV=0surround40:CARD=PCH,DEV=0デバイス名です。デバイス名と説明でパターンを検索し、説明に一致するデバイス名を見つけたいです。
私の期待は

aplay -L | pattern_match_command "Surround output"

surround40:CARD=PCH,DEV=0 同様に戻る

aplay -L | pattern_match_command "pulse"

返されますpulse
デフォルトでは、各デバイスのコンテキストは次のとおりです。

surround40:CARD=PCH,DEV=0
    HDA Intel PCH, ALC1220 Analog
    4.0 Surround output to Front and Rear speakers

現在説明が含まれていない行処理を使用しています。

aplay -L | grep "pulse"

どのツールを使用できるかについてのヒントがあります。使っていますubuntu 18.04

答え1

使用awk:

aplay -L |
pat='surround' awk '
    BEGIN { pat = tolower(ENVIRON["pat"]) }
    /^[^[:blank:]]/ { dev = $0; next }
    tolower($0) ~ pat { print dev }'

このawkコマンドは、空白以外の文字で始まる変数のすべての行を記憶しますdev。他の行が与えられたパターンと一致するたびにdev変数値が出力されます。

モードは環境変数を介して渡されますpat。小文字に変換され、変数awkに保存されますpat。パターンが行と一致すると、その行も小文字に変換されるため、この意味では、パターン一致は大文字と小文字を区別しません。

サンプルデータに基づいて、上記のコマンドの出力は次のようになります。

surround40:CARD=PCH,DEV=0

surroundこの行の単語と一致するので

4.0 Surround output to Front and Rear speakers

答え2

PCREサポートでGNU grepを使用する

mygrep() {
## helper  variables to make writing of regex tractable:-

## any nonwhitespace char which is not a colon
noncolon='(?:(?!:)\S)'
nonequal='(?:(?!=)\S)'

# these occur in the description line after the colon, akin to key=value pairs
pair="${nonequal}+=${nonequal}+"

# a header line comprises a run of noncolon nonwhitespace optionally followed by pairs
hdr="${noncolon}+(?::(?:,?${pair})+)?"

# description line is one that begins with a space and has atleast one nonwhitespace
descline='(?:\s.*\S.*\n)'

# supply your string to search for in the description section here ( case insensitive)
srch=$1
t=$(mktemp)

aplay -L | tee "$t" \
| grep -Pzo \
 "(?im)^${hdr}\n(?=${descline}*\h.*\Q${srch}\E)" \
| tr -d '\0' \
| grep . ||
grep -iF -- "$1" "$t"
}

## now invoke mygrep with the search string
mygrep  'card=pch'

出力:-

surround40:CARD=PCH,DEV=0
hw:CARD=PCH,DEV=0

関連情報