ファイルの特定のパターンにヘッダーを追加する

ファイルの特定のパターンにヘッダーを追加する

Linuxのさまざまな場所にヘッダーを追加する必要があるファイルがあります。 「ヘッダー」はファイルなので、最初の行にのみ追加できます。しかし、今では、特に新しいIPアドレスを見つける前に、複数の場所に同じヘッダーを追加したいと思います。実際にヘッダーを持つファイルは必要ありません。すべての出力を取得したら、awkまたはsedを介してテキストを追加するだけです。

ヘッダーは新しいIPアドレスを見つけた直後に挿入する必要があります。

リストは可変です。たとえば、ip 192.168.10.10には3つのエントリがありますが、さらに存在する可能性があります。たとえば、ip 192.168.10.33 には 2 つのエントリがありますが、より多くの場合があります。ポートはデフォルトでソートされます。 IP アドレスはソートされずにグループ化されます。

出力は次のとおりです。

192.168.10.10    1/1/2
192.168.10.10    1/1/3
192.168.10.10    1/1/4
192.168.10.33    1/1/2
192.168.10.33    1/1/6
192.168.10.20    1/1/6
192.168.10.20    1/1/7
192.168.10.20    1/1/10
192.168.10.20    1/1/18

出力が次のようになります。

SWITCH ID        PORT    
192.168.10.10    1/1/2
192.168.10.10    1/1/3
192.168.10.10    1/1/4

SWITCH ID        PORT              
192.168.10.33    1/1/2
192.168.10.33    1/1/6

SWITCH ID        PORT
192.168.10.20    1/1/6
192.168.10.20    1/1/7
192.168.10.20    1/1/10
192.168.10.20    1/1/18

答え1

これはヘッダーを追加するかなり長いawkスクリプトです。

NR==1 {
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
$1!=prev {
  print ""
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
$1==prev {
  print $0
}

ファイルとして保存してください。例えばaddheader.awk

このように電話してください

awk -f addheader.awk inputfile

それとも

commandproducinginput | awk -f addheader.awk

スクリプトの説明

awkの動作原理はおおよそ次のとおりです。

for every line of input
  for every rule
    if condition is true
      execute code block

「ルール」は条件とコードブロックのペアです。

上記のコードのルール例

NR==1 {
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}

これがNR==1条件です。中かっこ内の部分は{...}コードブロックです。

NR行番号(正確にはレコード番号)を含むawk固有の変数。したがって、NR==1最初の行だけが正確です。

最初の行では、ヘッダー行を印刷します。次に、実際の行($0現在の行のawk変数)を印刷します。次に、この行のIPアドレス($1現在の行の最初のフィールドのawk変数)を覚えておいてください。その後、awkが他の規則を考慮しないように、次の行に直接移動すると言います。ループから外れることをnext想像できます。breakfor every rule

$1!=prev現在のIPアドレスが前のアドレスと一致しない場合、次のルールの条件はtrueです。この場合、空白行を印刷します。それからタイトルがあります。その後、行自体があります。次に、この新しいIPアドレスを覚えておいてください。次に、次の行に移動します。

最後のルールは「Default Case」です。 IPアドレスが以前と同じ場合は、その行をそのまま印刷します。

next上記のルールはif else ifチェーンを効果的に形成します。

擬似コードではおおよそ次のようになります。

for every line:
  if is first line:
    print header then line
  else if IP adress is different than previous:
    print empty line then header then line
  else if IP adress is same to previous:
    print line

ボーナス:

次のバリエーションは同じです。

最後のコードブロックを省略します。

NR==1 {
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
$1!=prev {
  print ""
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
$1==prev

コードブロックが欠落している場合、デフォルトの動作はその行をそのまま印刷することです。

または条件を省略し、コードブロックを保持します。

NR==1 {
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
$1!=prev {
  print ""
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
{
  print $0
}

条件が欠落している場合、これは暗黙的に真です。これはnext、上記のルールがif else ifチェーンを効果的に形成するためです。最後のルールは最後のelseに似ているため、条件は必要ありません。

ルールの並べ替え

$1==prev
NR==1 {
  print "SWITCH ID        PORT"
  print $0
  prev=$1
}
$1!=prev {
  print ""
  print "SWITCH ID        PORT"
  print $0
  prev=$1
}

このように省略することはできますが、next私の好みは読みやすくなります。

共通コードを関数として抽出

func common() {
  print "SWITCH ID        PORT"
  print $0
  prev=$1
  next
}
NR==1 {
  common()
}
$1!=prev {
  print ""
  common()
}
$1==prev

すべての変数はawkのグローバル変数です。

関連情報