使用shell脚本从文件中删除行范围

时间:2017-02-20 05:46:22

标签: shell awk sed grep

我的测试文件test.txt如下:

destination mailerr  { file("/var/log/mail.err" fsync(yes)); };
log { source(src); filter(f_mailerr);  destination(mailerr); };

#
# and also all in one file:
#
destination mail { file("/var/log/mail"); };
log { source(src); filter(f_mail); destination(mail); };

destination mailwarn { file("/var/log/mail.warn"); };
log 
{ 
#source(src); 
filter(f_mailwarn); destination(mailwarn); };

我想使用shell脚本删除以下行

log 
{ 
#source(src); 
filter(f_mailwarn); destination(mailwarn); };

这些行可能会有不同的结构,如

log{ source(src); filter(f_mailwarn); destination(mailwarn); };
                          (or)
log
{ 
source(src); 
filter(f_mailwarn); 
destination(mailwarn); 
};
                           (or)
log
{ source(src); filter(f_mailwarn); destination(mailwarn); };
                           (or)
#   log { source(src); filter(f_mailwarn); destination(mailwarn); };
};

这些是可能性。我正在使用sed命令:

sed '/log/{:a;/destination(mailwarn);.*}/d;N;ba}' test.txt

但它会删除所有行,因为第一行它自己“log”来了。这么多“log”都出现在这个文件中,所以如何使用shell脚本删除特定的行。

4 个答案:

答案 0 :(得分:1)

您可以试试sed

sed  '/^[# ]*log/{:loop; /destination(.*}/d; /}/{n}; N; b loop;}' file

<强>解释

  • /^[# ]*log/ - 在{}匹配时开始处理阻止regex
  • /destination(.*}/d - 删除regex匹配时的模式空间。开始一个新的周期。
  • /}/{n} - 当找到}时,打印模式空间并读取下一行输入。 (用于打印非log...destination()行。
  • N - 这会将下一行输入附加到模式空间。
  • b loop - 这会将流量控制转移到loop

答案 1 :(得分:1)

如果文件不是太大,请使用-z选项一次性处理整个文件(@ SLePort注意这是GNU特定选项)

sed -z 's/log[ \t\n]*{[^}]*destination(mailwarn);[ \t\n]*};//g' test.txt
  • log比赛开始
  • [ \t\n]*{零个或多个非空格/制表符/换行符后跟{
    • 以避免错误匹配log/mail.warn"); };如果使用[^{]*{
  • [^}]*零个或多个非}个字符
  • destination(mailwarn);要匹配的字符串
  • [ \t\n]*};零个或多个非空格/制表符/换行符后跟};
  • 匹配的模式会在替换字符串为空时被删除


perl

类似
perl -0777 -pe 's/log\s*\{[^}]*destination\(mailwarn\);\s*};//g' test.txt

答案 2 :(得分:0)

使用sed:

sed '/^#*[[:blank:]]*log/{:a;/};/!{N;ba;s/\n//;};/destination(mailwarn)/d;}' file

log};的行添加到模式空间,在其中搜索destination(mailwarn),如果找到,则删除行。

答案 3 :(得分:0)

这是我完成工作的有点方式。它似乎适用于您发布的所有案例,但绝不是解决此问题的通用解决方案。

tr '\n' '\0' < test.txt | sed 's/log[^{}]*{[^}]*destination(mailwarn);[^}]*};//g' | tr '\0' '\n'

如果test.txt包含空字符,则可能无法正常工作。此命令主要查找log后跟{,然后到达} destination(mailwarn);,最后跟};,并删除此项匹配如果找到。

我希望其他人为这个问题发布更强大的解决方案,但这是我能够提出的唯一快速解决方案。