最初の行の最初の列と最後の列の値が同じ最後の行の2番目の列を印刷します。 [閉じる]

最初の行の最初の列と最後の列の値が同じ最後の行の2番目の列を印刷します。 [閉じる]

ここで望むのは、3番目の行が共通に並んでいるすべての行を表示し、この行セットに基づいて出力を提供することです。 (このテーブルには一般的な3行目以外に他のプロパティがありますが、今は見ていません。)出力を見る前に、これらの行グループを見てみましょう。私たちが持っているなら

入力する:

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  

これは、2つの行セットがあることを意味します。

共通の3番目の列値を持ち、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  

2番目は共通の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

これらのそれぞれについて、3つの値を維持したいと思います。

  1. 最初の行 最初の列

  2. 最後の行の2番目の列

  3. 共通の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入力を1行ずつ読み、各行に対してコードを実行します。
  • -a各行をスペースの @F 配列に分割します。
  • 最初の行の出力をスキップしますif defined $one(3番目の列は前の列とは異なりますが、まだ出力する項目はありません)。
  • 最後のブロックを印刷するには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 かを確認し、最初の行の最初の列と最後の行の 2 番目の列を印刷します。

より短いバージョン:

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)(オプション)2番目の部分、最後のフィールドが最初の部分と一致するゼロ行以上。
    • c) 最後のフィールドが最初の部分の最後のフィールドと一致する 3 番目の部分。同時に、3番目の部分の2番目のシーンを録音します。
    • d) ブロック全体を最初の部分の最初のフィールドに置き換え、次に3番目の部分の2番目のフィールド、最初の部分の最後のフィールドに置き換えます。

これは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

関連情報