ファイル内の 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) が変数に保存されa、 x がゼロに設定されます。attr:が見つかった場合、$0は old に変更され、$0その後にORS(改行)、その後に変数が続きますa

答え4

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

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

関連情報