Regex 如何删除以相同单词开头的连续行的第二行?

Regex 如何删除以相同单词开头的连续行的第二行?,regex,perl,bash,sed,awk,Regex,Perl,Bash,Sed,Awk,我有一个文本文件,其中以“TITLE”和“DATA”开头的换行,但有时会有以“TITLE”开头的重复行: 标题某事 数据一些数据 标题:其他内容 数据一些其他数据 标题更多 标题附加信息 数据更多的数据 我希望能够检测到以“TITLE”开头的重复行,并仅保留每对重复行的第一行。 我发现捕获它们的正则表达式是^TITLE.*\n^TITLE.*\n现在我想把它合并到一个一行的perl/bash/sed/awk命令中,该命令将删除第二行并输出文件的其余部分,但我想不出这一点。试试这一行: awk

我有一个文本文件,其中以“TITLE”和“DATA”开头的换行,但有时会有以“TITLE”开头的重复行:

标题某事
数据一些数据
标题:其他内容
数据一些其他数据
标题更多
标题附加信息
数据更多的数据

我希望能够检测到以“TITLE”开头的重复行,并仅保留每对重复行的第一行。
我发现捕获它们的正则表达式是
^TITLE.*\n^TITLE.*\n
现在我想把它合并到一个一行的
perl
/
bash
/
sed
/
awk
命令中,该命令将删除第二行并输出文件的其余部分,但我想不出这一点。

试试这一行:

 awk '/^TITLE/&&f{next;} {if ($0~/^TITLE/)f=1;else f=0}1' file
输出:

TITLE something
DATA some data
TITLE something else
DATA some other data
TITLE some more
DATA some more data
单向:

awk '$1!=p{print;p=$1}' file
Perl解决方案:

perl -ne 'print unless $t and /^TITLE/; $t = /^TITLE/'

它会记住前一行是否是
$t
变量中的标题。

这里有一种使用GNU的方法:

sed -r 'N; /(TITLE)[^\n]*\n\1/ s/\n.*//; P; D' infile
  • N
    将第二行放入模式空间
  • 匹配测试两行是否都以
    标题开始
  • 如果是,则删除第二行
  • P;D
    打印并删除图案空间中的第一行
输出:

TITLE something
DATA some data
TITLE something else
DATA some other data
TITLE some more
DATA some more data
编辑-处理任意数量的重复 正如Nikina Reklawyks在评论中指出的,上述解决方案仅适用于以
标题开始的两个连续行,为了处理任意数量的重复,可以添加如下简单循环:

sed -r ':a; N; /(TITLE)[^\n]*\n\1/ s/\n.*//; ta; P; D' infile
ta
语句使sed在
s//
成功时跳转到
:a
标签

另一种方法是使用
coreutils
中的
uniq
命令,这没有那么灵活,但在这种情况下效果很好:

uniq -w5 infile 

在我看来,你有两个字段组成的记录,标题和数据,如果你缺少第二个字段,你想删除记录。但这不是你在问题中问的。所以这里有一种方法可以满足你的要求:

awk '/^TITLE/&&!t{t=$0} /^DATA/&&t{print t;print;t=""}' inputfile
这里的想法是,当我们看到一个变量并且没有一个标题集时,我们将它设置为一个标题,然后只有当我们看到一个数据时才打印它。这适用于您提供的输入数据,如果我没有看错您的问题的话。输出为:

TITLE something
DATA some data
TITLE something else
DATA some other data
TITLE some more
DATA some more data
如您所见,数据集中的最后一个标题行已删除

这是另一种在awk中实现这一点的方法

awk '/^TITLE/&&t{next} t=0; /^TITLE/{t=1} 1' inputfile
在本例中,如果设置了
t
,则第一个表达式跳过标题。第二个表达式未设置
t
。第三个表达式为标题设置if,最后一个表达式(
1
)打印该行。当然,如果跳过第一个表达式中的行,则不会运行最后三个表达式。它生成与上面相同的输出,并且不需要查看
/^DATA/

最后,这是最少的代码,但最奇怪的逻辑:

awk '/^DATA/ || !t; {t=/^TITLE/}' inputfile

它打印所有数据行,或未设置
t
的任何行,然后有效地将
t
设置为布尔值,从而影响下一行的计算。如果在csh或tcsh中执行此操作,请注意感叹号,这些shell中的感叹号可能需要转义。

额外问题:如何仅保留最后一行
uniq-w5您的_文件
这只会删除第二行这样的连续行,删除除第一行以外的所有行将是一个自然的理想扩展名(imho)。换句话说,如何将其包装成“运行直到输出不再改变”循环?无论如何,感谢您提供了一个有用的起点。@NikanaReklawyks:是的,在这种情况下,添加循环很容易,请参见编辑。