使用 sed 注释除第一个之外的所有出现

使用 sed 注释除第一个之外的所有出现

我试图注释掉除第一个之外的所有其他事件。

原始样本.txt


#二

样本.txt


#二
##二
#二

我只能注释掉所有发生的事情。使用:

sed -i /两个/s/^/#/

但这也注释掉了已经注释的事件。这也注释掉了发现该事件的行。我该如何解决这个问题?我正在 ubuntu 基线映像上测试这个,所以我不能特别安装任何东西。

答案1

至少使用 GNU sed(Ubuntu 上默认应该有)你可以执行诸如0,/pattern/.所以也许是这样的:

$ sed '0,/^two/!s//#&/' original.txt 
one
two
three
#two
#two
#two

这表示“对于除了第 0 行和第一个匹配项之间的每一行/^two/,替换为,后跟您刚刚匹配的内容。替换中的空模式与前面的正则表达式匹配,并且/^two/替换刚刚匹配的内容 - 一个非高尔夫版本将会#//&

sed '0,/^two/!s/^two/#two/' original.txt

由于^two锚定到行的开头,因此它与已注释的事件不匹配 - 如果是不是你想要什么,删除^.

答案2

perl -p -i -e '$_ = ("#" x $count{$_}++) . $_' your-file

产生您的预期结果。它为每行添加与#之前出现过的相同行一样多的前缀。

上面的选项-i编辑文件n-place(实际上-i在某些sed实现中找到的选项显然是从 复制的perl)。

答案3

sed众所周知,他不善于计算。使用以下方法更容易awk

$ awk '/^two/ { if (++count > 1) $0 = "#" $0 }; 1' file
one
two
three
#two
#two
#two

在首先看到被忽略的此类行之后,这会#在以字符串开头的每一行前面添加一个字符。然后,无论是否修改,所有行都会被打印(通过代码中的two尾部,可以用 替换)。1{ print }

答案4

这并不完全是您想要的,但如果我理解正确的话,您希望最终得到一个文件,其中未注释的条目是唯一的,其他所有内容都已注释。我不知道你将如何做到这一点,但一种解决方法是保持原始文件完好无损,并最终得到另一个具有唯一文件的文件......

$ cat sample.txt | uniq | grep -v ^#  
one
three
two

相关内容