比较文本文件中的行

时间:2017-02-02 18:07:45

标签: awk sed text-processing

我有一个这样的文件,用标签分隔:

1 abc
2 abc
3 def
4 abc
1 abc
5 def

我想通过比较第二列的连续行来生成另一个文件。 deisred输出是这样的:

1 2
1 4
3 5

我试过这种方式,但没有运气:

awk '{
dat[$2]++;
}
END{
for (var in dat)
if (var==$2){print $1,previous};
previous =$1}' file.txt 

使用awk实现此目的的任何建议

3 个答案:

答案 0 :(得分:1)

这确实比较了所有不仅是连续的,只有在有匹配时打印,因此将忽略唯一条目

$ awk '{if($2 in a) print $1,a[$2]; else a[$2]=$1}' file

2 1
4 1
1 1
5 3

请注意,1 1条目出现,因为您在输入文件中有1 abc两次。

将列更改为if语句中的print a[$2],$1。要消除重复条目的自引用,您可以在打印之前添加另一个条件if($2!=a[$1])

答案 1 :(得分:0)

如果您对输入文件进行排序,这会快得多:

$ sort -k 2d data| awk '{ if (last==$2 && $1 != firstnum) { printf("%d\t%d\n", firstnum, $1); }; if (last!=$2) { last=$2; firstnum=$1; printf("%d\t%d\n", firstnum, firstnum); }}'
1   1
1   2
1   4
3   3
3   5

我不确定您是否要打印(1,1)和(3,3)对。但我想如果你有一个只出现在一行上的键,你可能想要打印出来,所以我把它留了下来。如果你不想要它,可以取出第二个printf。

答案 2 :(得分:0)

awk '   {
        if ( ! ( $2 in Ps ) ) Os[++Oi] = $2
        # Line nr reference
        Ps[$2] = Ps[$2] " " NR
        # first field reference
        Ps[$2] = Ps[$2] " " $1
        }
     END {
        for ( i=1; i <= Oi; i++ ) {
           Size = split( Ps[ Os[ i]], aPls)
           for ( j = 2; j <= Size; j++) {
              printf( "%s\t%d\n", aPls[1], aPls[ j])
              }
           }
        }
     ' YourFile
  • 你需要记住第一次阅读1)第一次出现的地方2的地方,也引用其他具有相同模式的行
  • 我选择将它放在2个数组中,只读一次文件,但你可以重读同一个文件并在第二次运行时打印
  • 数组
    • Ps包含模式的所有出现位置(索引是模式)
    • Os包含首次出现的列表,索引是顺序的,有序的
相关问题