在檔案中的兩個正規表示式模式之間增量交換行

在檔案中的兩個正規表示式模式之間增量交換行

我正在嘗試使用 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 機器上的任何 shell 中使用任何 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 space( h)中
  • pattern space從( n)中的文件中取得下一行
  • pattern spacehold space( G) 交換(相當於換行)

列印您遇到的每一行: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:找到,則將目前輸入 record( $0) 儲存到變數中a,並將 x 設為零。如果attr:找到,$0則將 d 變更為 old ,$0然後ORS(newline) ,然後是變數a

答案4

我們可以使用 POSIX sed 結構來翻轉上述行。

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

相關內容