ファイルの2つの正規表現パターン間で行を徐々に交換します。

ファイルの2つの正規表現パターン間で行を徐々に交換します。

Bashスクリプトを使用してファイルに対していくつかのテキスト処理を実行しようとしています。目的は、「attribute:」タグの下にインデントされた「field:」で始まるすべての行を「-attr:」で始まる次の関連行に置き換えることです。

これまで私の正規表現パターンはタグと一致する必要があると思います。

/ *field:(.*)/g

/ *- attr:(.*)/g

しかし、必須フィールドを解析して正しく置き換えるロジックは成功しませんでした。

入力テキストの例

- metric: 'example.metric.1'
  attributes:
      field: 'example 1'
    - attr: 'example1'
      field: 'example 2'
    - attr: 'example2'
      field: 'example 3'
    - attr: 'example3'
      field: 'example 4'
    - attr: 'example4'
- metric: 'example.metric.2'
  attributes:
      field: 'example 5'
    - attr: 'example5'
      field: 'example 6'
    - attr: 'example6'
      field: 'example 7'
    - attr: 'example7'
- metric: 'example.metric.3'
...

希望の出力

- metric: 'example.metric.1'
  attributes:
    - attr: 'example1'
      field: 'example 1'
    - attr: 'example2'
      field: 'example 2'
    - attr: 'example3'
      field: 'example 3'
    - attr: 'example4'
      field: 'example 4'
- metric: 'example.metric.2'
  attributes:
    - attr: 'example5'
      field: 'example 5'
    - attr: 'example6'
      field: 'example 6'
    - attr: 'example7'
      field: 'example 7'
- metric: 'example.metric.3'
... 

どうやってこれを達成できますか?

答え1

すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ awk '$1=="field:"{s=ORS $0; next} {print $0 s; s=""}' file
- metric: 'example.metric.1'
  attributes:
    - attr: 'example1'
      field: 'example 1'
    - attr: 'example2'
      field: 'example 2'
    - attr: 'example3'
      field: 'example 3'
    - attr: 'example4'
      field: 'example 4'
- metric: 'example.metric.2'
  attributes:
    - attr: 'example5'
      field: 'example 5'
    - attr: 'example6'
      field: 'example 6'
    - attr: 'example7'
      field: 'example 7'
- metric: 'example.metric.3'

いくつかの行の後にスペースがない場合、またはfield:何らかの理由で必死に正規表現を使用したい場合は、必要に応じてまたはに$1=="field:"変更$1~/^field:/してください。/^[[:space:]]*field:/

答え2

そしてsed

sed -n '/^ *field: /{h;n;G};p' data

キーワードが一致すると、field次のようになります。

  • 現在の行をhold spaceh)内に保存します。
  • pattern space()n内のファイルから次の行を取得します。
  • ( )pattern spaceに交換されます(改行と同じ)。hold spaceG

出会うすべての行を印刷します。p

答え3

使用awk:

awk '{if ($1 == "field:") {a=$0;x=0} 
else if (/- attr:/) {$0 = $0 ORS a; x=1} else {x=1}}x' input

このコマンドでfield:見つかった場合は、現在の入力レコード($0)を変数に保存し、axを0に設定します。attr:見つかったら、$0dをoldに変更し$0ORS改行)、変数を変更しますa

答え4

POSIX sed 構造を使用して、上の行を反転できます。

sed '/attr:/!x;$G' file

関連情報