In the following configuration file
/etc/fine-tune.conf
We have duplicate lines as
clean_history_in_os=true
we want to delete all the lines that include clean_history_in_os=true except the first matched line in the file
what I did until now is that
sed -i '/clean_history_in_os=true/d' /etc/fine-tune.conf
but the problem is that sed delete all "clean_history_in_os=true" lines
I will happy to get ideas to solve this issue ,
答案 0 :(得分:3)
使用Perl
perl -i -ne'next if /clean_history_in_os=true/ && ++$ok > 1; print' file
这将使计数器在该行上递增计数,如果> 1
会跳过该行,否则打印
关于如何将模式作为外壳变量传递给Perl的问题出现了。下面我假设外壳变量$VAR
包含字符串clean_history...
在所有这些中,shell变量直接用作正则表达式中的模式。如果它是问题中的文字字符串,则下面的代码按给定方式运行。但是,如果可能有特殊字符,则应将其转义;因此在正则表达式中使用时,您可能需要在模式前加上\Q
。作为一般说明,应该注意不要使用外壳程序的输入来运行代码(例如在/e
下)。
将其作为参数传递,然后可以在@ARGV
中使用perl -i -ne'
BEGIN { $qr=shift; };
next if /$qr/ && +$ok > 1; print
' "$VAR" file
其中BEGIN
block在BEGIN
阶段在运行时之前运行(因此以下迭代不适用)。 shift在其中从@ARGV
中删除了第一个元素,在上面的调用中,它是$VAR
中的值,该值首先由shell插入。然后,文件名file
保留在@ARGV
中,因此可以在-n
下进行处理(文件已打开,并且其行遍历了)
使用-s
switch,它启用程序的命令行开关
perl -i -s -ne'next if /$qr/ && +$ok > 1; print' -- -qr="$VAR" file
--
(位于''
下的单行程序之后)标志着该程序的参数开始;然后-qr
将变量$qr
引入程序,并为其分配一个如上所述的值(仅使用-qr
,变量$qr
便获得值1
,因此是一个标志)。
任何此类选项必须在可能的文件名之前,并将它们从@ARGV
中删除,以便程序可以正常处理提交的文件。
导出bash变量,使其成为环境变量,然后可以通过%ENV
hash
export $VAR="clean_history..."
perl -i -ne'next if /$ENV{VAR}/ && +$ok > 1; print' file
但是我宁愿推荐前两个选项中的任何一个。
对注释中给出的问题的改进规定,如果短语clean_...
以#
开头,则应完全跳过该行。单独测试最简单
next if /#$qr/; next if /$qr/ && +$ok > 1; print
或者,依靠短路
next if /#$qr/ || (/$qr/ && +$ok > 1); print
第一个版本不太容易出错,可能更聪明。
答案 1 :(得分:2)
您可以使用此awk
删除除第一行以外的所有匹配行:
awk '!(/clean_history_in_os=true/ && n++)' file
要将文件保存到位,可以使用以下gnu awk
命令:
awk -i inplace '!(/clean_history_in_os=true/ && n++)' file
否则将临时文件用作:
awk '!(/clean_history_in_os=true/ && n++)' file > $$.tmp && mv $$.tmp file
这里是一种sed
解决方案,可以做到这一点:
sed -i -n '0,/clean_history_in_os=true/p;/clean_history_in_os=true/!p' file