Linux命令找到两个可比较的行

时间:2014-05-07 13:33:59

标签: linux sed

我有以下排序顺序的数据(这里数据按照第一个v1,然后是v2,然后是v3,然后是v4进行排序):

v1=1    v2=8513481      v3=119330184    v4=0
 v1=1    v2=8521383      v3=119330182    v4=0
 v1=1    v2=10630231     v3=60529116     v4=18
 v1=1    v2=60528877     v3=60529221     v4=17
 v1=1    v2=90351079     v3=90351078     v4=20
 v1=1    v2=271669588    v3=271669683    v4=101
 v1=2    v2=8513481      v3=10583646     v4=0
 v1=2    v2=10175437     v3=10175436     v4=0
 v1=2    v2=10630231     v3=60528947     v4=17
 v1=2    v2=10630231     v3=60529119     v4=18
 v1=2    v2=10630232     v3=605291191     v4=18

现在我想找出两条线的v1和v2相等的行。即在上面给出的数据中,我想找到以下形式的行:

 v1=2    v2=10630231     v3=60528947     v4=17
 v1=2    v2=10630231     v3=60529119     v4=18

我知道如何在python中通过比较连续的行以及每当输出该行的匹配时这样做。是否有一种简单的方法可以使用像sed等linux命令来做同样的事情。我知道如何在给出两个值时使用sed查找单词,但我不知道如何在这个上下文中使用sed。我们非常感谢您的一些解释。

4 个答案:

答案 0 :(得分:3)

使用awk

会更容易一些
awk '{
    lines[$1,$2]=(lines[$1,$2]?lines[$1,$2] RS $0:$0)
    dups[$1,$2]++
}
END {
    for(line in lines) 
        if(dups[line]>1) print lines[line]
}' file
v1=2    v2=10630231     v3=60528947     v4=17
v1=2    v2=10630231     v3=60529119     v4=18
  • 我们创建了两个数组。 linesdups
  • 当第一列和第二列被多次看到时,我们增加计数。我们使用dups数组。
  • 在我们的lines数组中,我们检查是否存储了具有相同第一列和第二列的行。如果我们将重复的行附加到它。
  • END块中,我们遍历lines数组。如果在我们的dups数组中多次找到第一列和第一列,我们会打印这些行。

或者,如果您不想将整个文件保留在内存中,则可以执行以下操作(因为您声明您的数据已经排序):

awk '($1==c1 && $2==c2){print line RS $0}{line=$0;c1=$1;c2=$2}' file
  • 我们将变量line指定为整个当前行,c1指定为第1列,将c2指定为第2列。
  • 如果当前行的第1列和第2列与前一列和第二列相同,则打印上一行和当前行。

答案 1 :(得分:1)

首先让我首先说明你所显示的列表并没有严格按照Linux意义排序(空格和制表符会影响排序)。针对您的问题,最好的Linux解决方案是使用awk。这是一个应该做你想要的命令:

awk -e '{cur=$1 " " $2; if (NR>1 && cur==prev) {print "line:"NR " " cur} prev=cur}' < input_file

所有这一切都是比较由输入文件的第一列和第二列的组合形成的字符串($ 1和$ 2;用更清洁输出的空格分隔),我们称之为 cur 来自上一个输入行的相同字符串,我们称之为 prev 。如果两个字符串匹配,我们输出行号和结果。我们还添加了一个条件来跳过文件的第一行,因为还没有什么可比较的。

答案 2 :(得分:1)

这可能适合你(GNU sed):

sed -rn '$!N;/^\s*(\S+)\s+(\S+)\s+.*\n\s*\1\s+\2/p;D' file

这使用后引用来比较两行并打印那些复制前两个值的行。

然而,如果重复项可以是三个或更多个连续行,则可以使用另一种方法。使用保持缓冲区打印并标记重复项。当遇到重复后跟非重复行时,也会打印最后一个重复行并重置标志:

sed -rn '$!N;/^\s*(\S+)\s+(\S+)\s+.*\n\s*\1\s+\2/{h;P;D};x;/./{z;x;P;D};x;D' file

答案 3 :(得分:0)

一种方法是找出行开头有多少个字符相同(看起来大约是25?),只通过uniq比较那么多字符:

uniq --check-chars=25 --repeated < input_file

要打印这两行,请使用--all-repeated代替--repeated