打印第一行的第一列和最后一行的第二列,其中最后一列具有相同的值

打印第一行的第一列和最后一行的第二列,其中最后一列具有相同的值

这里的愿望是查看具有公共、排序的第三行的任何行,并根据这组行给出输出。 (请注意,除了常见的第三行之外,该表还有其他属性,但现在我们不会查看它们。)在查看输出之前,让我们看看这些行组。如果我们有

输入:

0.016   0.032   1  
0.032   0.048   1  
0.048   0.064   1  
0.064   0.08    1  
0.08    0.096   1  
0.096   0.112   1  
0.112   0.128   0  
0.128   0.144   0  
0.144   0.16    0  
0.16    0.176   0  
0.176   0.192   0  
0.192   0.208   0  

这意味着我们有两组行:

具有共同的第三列值,1

0.016   0.032   1  
0.032   0.048   1  
0.048   0.064   1  
0.064   0.08    1  
0.08    0.096   1  
0.096   0.112   1  

第二个具有共同的0价值。

0.112   0.128   0  
0.128   0.144   0  
0.144   0.16    0  
0.16    0.176   0  
0.176   0.192   0  
0.192   0.208   0

对于其中每一个,我们希望保留三个值:

  1. 第一行第一列

  2. 最后一行的第二列

  3. 共同的第三列值

这最终给了我们

期望的输出:

0.016 0.112 1  
0.112 0.208 0  

答案1

Perl 来救援!

perl -ane '
    sub out { print "@_\n" }
    if ($F[2] != $three) {
        out($one, $two, $three) if defined $one;
        ($one, $three) = @F[0, 2];
    }
    $two = $F[1];
    END { out($one, $two, $three) }
    ' < input > output
  • -n逐行读取输入并运行每一行的代码;
  • -a将每一行拆分为空格上的 @F 数组;
  • 跳过if defined $one输出第一行(它的第三列与前一列不同,但还没有任何内容可输出);
  • 需要 END 块来打印最后一个块

答案2

我使用以下方法做到了awk

awk 'BEGIN{f=0;OFS=" ";t=0;}  {if(f == 0 && $3 == 1) {ff=$1;f=1;next} if(f==1 && $3 == 1) {r=$2;} \
 if(t == 0 && $3 == 0) {print ff,r,1;ff=$1;t=1;next} if(t==1 && $3 == 0) {r=$2;}}  END{print ff,r,0}' file

它看起来很大,但方法很简单,检查最后一列是1还是0,然后打印第一行的第一列和最后一行的第二列。

较短版本:

awk 'BEGIN{f=0;OFS=" ";t=0;}  {if($3 == 1) {if(f==0){ff=$1;f=1;next} else{r=$2;}} \
else{if(t==0){print ff,r,1;ff=$1;t=1;next} else{r=$2;}}}  END{print ff,r,0}' file

最初 f 和 t 的值为 0,然后 ff 第一次$3==0等于第一列 和f=1,对于接下来的行,我们将采用r=$2。同样对于$3==0.

答案3

您可以通过Perl读取文件并对其运行正则表达式来完成此操作:

$ perl -0777 -pe 's/^(\H+).*\h(\d+)\n(?:.*\h\2\n)*(?:.*\h(\H+)\h+\2$)/$1 $3 $2/mg' inp.file

输出:

0.016 0.112 1
0.112 0.208 0

解释:

  • 将整个文件合并到一条记录中,$_然后对其进行正则表达式操作。
  • 正则表达式本质上是查找最后一个字段匹配的文本块,然后对其进行操作。
  • 它通过 3 个正则表达式部分查看该块:
    • a) 块的第一部分到第一个换行符。
    • b) (可选)第二部分,0 行或多行,其最后一个字段与第一部分的匹配。
    • c) 第三部分,其最后一个字段与第一部分的最后一个字段匹配。同时我们记录第三部分的第二场。
    • d) 现在我们将整个块替换为第一部分的第一个字段,然后是第三部分的第二个字段,以及第一部分的最后一个字段。

这是Perl上面显示的相同代码,但散布着独立的注释并为了清晰起见进行了格式化:

$ perl -0777 -pe '
   s{
      ^(\H+).*\h(\d+)\n   (?#:the first row.)
      (?:.*\h\2\n)*       (?#:0 or more rows, whose last field matches the 1st row"s last.)
      (?:.*\h(\H+)\h+\2$) (?#:the  last  row, whose last field matches the 1st row"s last.)
   }{
      my($first_row_first_col, $last_row_second_col, $common_index) = ($1, $3, $2);
      join " ", $first_row_first_col, $last_row_second_col, $common_index;
   }gemx;
' inp.file

相关内容