将行附加到文本块,增加前一行的值

将行附加到文本块,增加前一行的值

我有一个包含以下内容的文本文件名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

假设我想向其中一个块添加一个新行,例如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

正如我在对拉尔夫的回答的评论中所说,这项工作有更好的工具,例如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各种(较小的)替换,但没有意识到您实际上可以在其中进行编程。显然,这是一个相当弱的“机器”,因为它只有两个寄存器,并且语言相当晦涩。

由于sed不接受输入变量,我将其设置为一个使用动态程序sh调用的脚本sed,该程序是通过用命令行中的实际标记替换 BLOCK 和 ENTRY 来准备的。该替换是通过单独的简单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
)"

非常感谢您提出这个(对我来说)有趣的挑战。

相关内容