次の内容を含むテキストファイル名があります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
に新しい項目がある場合、新しい項目が追加されると、数値が自動的に増加する必要があります。希望の出力LETTER
whitelist
[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
に設定しました。交換は、項目挿入を実装するための特定のプログラムを準備するために別々の単純な交換で行われます。sh
sed
sed
以下のスクリプトがそのタスクを実行しているようです。呼び出されると、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
)"
この面白い挑戦に感謝します。