web-dev-qa-db-ja.com

bashのテキストファイルからテキストを抽出する

すべて1行の大きなテキストファイルがあります。本文には_foo=12345_のようなセクションがいくつかあり、ファイルの残りの部分を無視して、それらすべてを別々の行として抽出する必要があります。

例えば:

_random junk foo=12345 more junk random junk foo=2345 junk foo=7654 junk random foo=5432 junk
_

私が抜け出したいのは:

_12345
2345
7654
5432
_

foo=([0-9]+)を抽出するための正規表現の記述方法は知っていますが、それをテキストに適用して行をbashで出力する方法がわかりません。

3
Roger Gilbrat
_$> echo "random junk foo=12345 more junk random junk foo=2345 junk foo=7654 junk random foo=5432 junk" | grep --only-matching --Perl-regexp "(?<=foo=)[0-9]+"
12345
2345
7654
5432
_

ここで行ったことは、"(?<=foo=)[0-9]+"でlookbehindregexを使用することです。

awkを使用して、長い行をレコードに解析します。

awk 'BEGIN{FS="=";RS=" "}/^foo=/{print $2}'

これにより、各「Word」が個別のレコードとして設定され、そのWord内で「=」を使用してフィールドが個別に設定されます。次に、左側が「foo」の場合、「=」の右側を出力するだけです。 '='がない場合、最初のフィールドはレコード全体と同じであるため、$1=="foo"の代わりに正規表現を使用する必要があります。

4
Arcege

これは、シェル構造のみで行うことができます。データを変数に読み取り、この変数を$IFS(デフォルトでは空白)の文字で分割し、必要なチャンクを保持します。二重引用符の外側の変数置換では、単語の分割(ここで必要)とファイル名の生成(別名、グロブ、不要)が行われるため、最初にset +fでグロブをオフにします。

set +f
for x in $(cat /path/to/file); do
  case "$x" in
    foo=*) echo "${x#*=}";;
  esac
done
set -f

catを呼び出す代わりに、readビルトインを使用できます。

set +f
read -r line </path/to/file
for x in $line; do …