这里的愿望是查看具有公共、排序的第三行的任何行,并根据这组行给出输出。 (请注意,除了常见的第三行之外,该表还有其他属性,但现在我们不会查看它们。)在查看输出之前,让我们看看这些行组。如果我们有
输入:
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
对于其中每一个,我们希望保留三个值:
第一行第一列
最后一行的第二列
共同的第三列值
这最终给了我们
期望的输出:
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