連続して繰り返される行の間に行を挿入するには?

連続して繰り返される行の間に行を挿入するには?

仮想IPアドレスを追加したいが、連続した2つの重複行を見つけた後にのみ可能です。

私はLinuxシステムで作業しており、これが私の入力ファイルです。

  IP_Remote_Address
     Address : 192.168.1.1
  IP_Remote_Address
     Address : 192.168.1.2
  IP_Remote_Address
     Address : 192.168.1.3
  IP_Remote_Address
  IP_Remote_Address
     Address : 192.168.1.4
  IP_Remote_Address
     Address : 192.168.1.5
  IP_Remote_Address
     Address : 192.168.1.6
  IP_Remote_Address
     Address : 192.168.1.7
  IP_Remote_Address
  IP_Remote_Address
     Address : 192.168.1.8

私が望む出力:

  IP_Remote_Address
     Address : 192.168.1.1
  IP_Remote_Address
     Address : 192.168.1.2
  IP_Remote_Address
     Address : 192.168.1.3
  IP_Remote_Address
     Address : NOT_FOUND
  IP_Remote_Address
     Address : 192.168.1.4
  IP_Remote_Address
     Address : 192.168.1.5
  IP_Remote_Address
     Address : 192.168.1.6
  IP_Remote_Address
     Address : 192.168.1.7
  IP_Remote_Address
     Address : NOT_FOUND
  IP_Remote Address
  Address : 192.168.1.8

次の行がありますが、見つかった最初の重複項目のみを置き換えます。

awk '{print $0; if((getline nl) > 0){ print ($0!="IP_Remote_Address" && $0 == nl)? nl=$0"INSERT_NOT_FOUND_ABOVE" : nl }}' file.txt

後でsedを使用して文字列を次のように置き換えることができますINSERT_NOT_FOUND_ABOVE"

sed '/INSERT_NOT_FOUND_ABOVE/i Address : NOT_FOUND' file.txt > new_file.txt

私の唯一の問題は、すべての連続重複を検出することができず、最初の重複のみを見つけることです。

答え1

awk:

awk 'p==$0{print "     Address : NOT_FOUND"}{p=$0}1'

やや無邪気なソリューションです。

  • p==$0IF p ==現在の行
    • その後、印刷not found
  • p=$0SET p = 現在の行
  • 1: 印刷

連続した重複行を処理します。


指摘したとおり@サンフランシスコ問題のコメントに「おそらく最後のIPもなくなったでしょう?」- UPS。これを考えなければなりません。

だから:

awk -v e='Address : NOT_FOUND' 'p==$0{print e}{p=$0}END{if($1 ~ "IP")print e}1'
  • 設定e=挿入するテキスト
  • p==$0IF p ==現在の行
    • 次に変数を印刷します。e
  • p=$0SET p = 現在の行
  • ENDe現在の行に以下が含まれているかどうかを印刷するIP
  • 1: 印刷

ここエラー文字列2回使うので変数として追加しました。 (そしてこの記事では読みやすくするために切り捨てられました)。

答え2

スライドウィンドウを使用してGNU sedでこれを達成する1つの方法は次のとおりです。

解析.sed

# Handle last-line-error
$ { /IP/ s/$/\n   Address : NOT_FOUND/; }

# Always keep 2 lines in pattern-space
N

# If the lines are identical
/^([^\n]*)\n\1$/ { 

  # Add error text
  s/\n/\n   Address : NOT_FOUND\n/

  # Ensure we still only have 2 lines in pattern-space
  P
  s/[^\n]*\n//
}

# Print line 1 and delete it from pattern-space
P
D

以下は、3つのエラーと最後の行にエラーがある修正済みテストテキストです。

IP_Remote_Address
   Address : 192.168.1.1
IP_Remote_Address
   Address : 192.168.1.2
IP_Remote_Address
   Address : 192.168.1.3
IP_Remote_Address
IP_Remote_Address
IP_Remote_Address
IP_Remote_Address
   Address : 192.168.1.4
IP_Remote_Address
   Address : 192.168.1.5
IP_Remote_Address
   Address : 192.168.1.6
IP_Remote_Address
   Address : 192.168.1.7
IP_Remote_Address
IP_Remote_Address
   Address : 192.168.1.8
IP_Remote_Address

次のように実行します。

sed -Ef parse.sed infile

または1行で:

<infile sed -E '${/IP/ s/$/\n   Address : NOT_FOUND/};N;/^([^\n]*)\n\1$/{s/\n/\n   Address : NOT_FOUND\n/;P;s/[^\n]*\n//};P;D'

どちらの場合も出力:

IP_Remote_Address
   Address : 192.168.1.1
IP_Remote_Address
   Address : 192.168.1.2
IP_Remote_Address
   Address : 192.168.1.3
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : 192.168.1.4
IP_Remote_Address
   Address : 192.168.1.5
IP_Remote_Address
   Address : 192.168.1.6
IP_Remote_Address
   Address : 192.168.1.7
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : 192.168.1.8
IP_Remote_Address
   Address : NOT_FOUND

答え3

拡張正規表現モードでは、ストリームエディタユーティリティsedのGNUバージョンを使用してください。

sed -Ee '
  x;1d;G
  ${/\n\s*IP_/ba;}
  /^(.*)\n\1$/{
    g;:a;p;c\
   Address : NOT_FOUND
    b
  }
  $!s/\n.*//
' file
  • 現在の行は記憶空間に入り、前の行はパターン空間に入ります。
  • 保留とパターンスペース(つまり、前の行と現在の行)が一致する場合は、対応する行+見つからない行を印刷します。
  • 最後の行は /IP_/ で、見つからない行も追加します。

関連情報