テキストブロックに行を追加して、前の行の値を増やします。

テキストブロックに行を追加して、前の行の値を増やします。

次の内容を含むテキストファイル名がありますclass.txt

[serverClass:MAIL]
whitelist.0=LATE
whitelist.1=ONTIME

[serverClass:LETTER]
whitelist.0=FIRST
whitelist.1=SECOND
whitelist.2=THIRD
whitelist.3=FOURTH

[serverClass:NOTES]
whitelist.0=TEST
whitelist.1=CAR
whitelist.2=SPOON
whitelist.3=GAME

ブロックの1つに新しい行を追加したいとします。たとえば、ブロックSAMPLEに新しい項目がある場合、新しい項目が追加されると、数値が自動的に増加する必要があります。希望の出力LETTERwhitelist

[serverClass:MAIL]
whitelist.0=LATE
whitelist.1=ONTIME

[serverClass:LETTER]
whitelist.0=FIRST
whitelist.1=OLD
whitelist.2=NEW
whitelist.3=FOURTH
whitelist.4=SAMPLE

[serverClass:NOTES]
whitelist.0=TEST
whitelist.1=CAR
whitelist.2=SPOON
whitelist.3=GAME

これを行う方法はありますかsed

答え1

Ralphの答えに対する私の意見で述べたように、これにはより良いツールがあります。たとえば、awk段落モードを使用しwhitelist.0=SAMPLE、ブロックが空の場合は追加し、それ以外の場合は抽出しないことがあります。最後のフィールド(この場合は行)で始まり、whitelist.NR+1=SAMPLEブロックに追加します。

awk -vRS= -vORS='\n\n' 'BEGIN{z="whitelist.0=SAMPLE";FS="\n"}
/LETTER/{if (/[0-9]=/){split($NF, a, /[.=]/);sub(/0/, a[2]+1, z)}
sub (/$/,"\n"z ,$0)};1' infile

答え2

すごい!今私は新しいことを学びました。私はsedさまざまな(マイナーな)代替を使用しましたが、実際にプログラムできることに気づいていませんでした。明らかに、これはレジスタが2つだけで、言語が非常にあいまいだったので、やや弱い「マシン」でした。

入力変数を受け入れないため、コマンドラインでBLOCKとENTRYを実際のトークンに置き換えて、準備された動的プロシージャを使用して呼び出されるスクリプトsedに設定しました。交換は、項目挿入を実装するための特定のプログラムを準備するために別々の単純な交換で行われます。shsedsed

以下のスクリプトがそのタスクを実行しているようです。呼び出されると、addentry次のように呼び出されます。

$ addentry LETTER SAMPLE < data

入力データを再生成し、挿入された項目を出力として持ちます。必要に応じて「場所で編集」する-iオプションがあるとしますsed

#!/bin/sh

/bin/sed -n "$(cat << EOF | sed -e "s/BLOCK/$1/g;s/ENTRY/$2/g"
# Initialize hold space with 0
1 { x ; /^$/ s/^$/0/; x }

# Lines outside the interesting block are just printed
/\s*serverClass:BLOCK/,/^$/! { p }

# Lines of the interesting block are considered more in detail
/\s*serverClass:BLOCK/,/^$/ {

  # The final empty line is replaced by the new entry, using the line
  # counter from the "hold buffer"
  /^$/ { g; s/\(.*\)/whitelist.\1=ENTRY/p; s/.*//p; b xx }

  # print the line
  p

  # Jump forward for the block leader (note xx is a label)
  /serverClass:/ { b xx }

  # Increment hold space counter
  # (Only handles 0-9 here; room for improvement)
  x; y/0123456789/1234567890/; h

  # If the block ends the file without blank line, then add the
  # new entry at end.
  $ { g; s/\(.*\)/whitelist.\1=ENTRY/p; b xx }

  # Label xx is here
  :xx
}
EOF
)"

この面白い挑戦に感謝します。

関連情報