ある行のテキストを別の行の末尾に追加するには?

ある行のテキストを別の行の末尾に追加するには?

ソース出力ファイルには、次のテキストブロックと追加情報が含まれています。

 Projecting out rotations and translations

 Force Constants (Second Derivatives of the Energy) in [a.u.]
                             GX1         GY1         GZ1         GX2         GY2     
           GX1           0.6941232
           GY1           0.0187624   0.0156533
           GZ1          -0.1175495  -0.0980708   0.6144300
           GX2          -0.6074291  -0.0036667   0.0229726   0.6228918
           GY2           0.0069881  -0.0013581   0.0085087   0.0023190   0.0014047
           GZ2          -0.0437815   0.0085087  -0.0533084  -0.0145287  -0.0088007
           GX3          -0.0866941  -0.0150957   0.0945769  -0.0154627  -0.0093070
           GY3          -0.0257505  -0.0142952   0.0895621   0.0013477  -0.0000466
           GZ3           0.1613309   0.0895621  -0.5611216  -0.0084438   0.0002920
                             GZ2         GX3         GY3         GZ3     
           GZ2           0.0551377
           GX3           0.0583102   0.1021568
           GY3           0.0002920   0.0244027   0.0143418
           GZ3          -0.0018293  -0.1528871  -0.0898540   0.5629509

これまで、関連ヘッダーと一緒に必要なデータを正常に分離し、[grep]と[awk](下)を使用してログファイルに印刷しました。

#!/bin/bash

rm Hessian.log

for i  in *.out
do
grep -H -A16 "Force Constants (Second Derivatives of the Energy)" $i | tail -n +1 | awk ' NR == 2 {printf "     "" %10s %10s %10s %10s %10s \n", $2,$3,$4,$5,$6} NR == 3, NR == 11 {printf "%5s %10s %10s %10s %10s %10s\n", $2,$3,$4,$5,$6,$7} ' >> Hessian.log
echo "" >> Hessian.log
done

次を生成します。

          GX1         GY1         GZ1         GX2         GY2     
GX1    0.6941232
GY1    0.0187624   0.0156533
GZ1   -0.1175495  -0.0980708   0.6144300
GX2   -0.6074291  -0.0036667   0.0229726   0.6228918
GY2    0.0069881  -0.0013581   0.0085087   0.0023190   0.0014047
GZ2   -0.0437815   0.0085087  -0.0533084  -0.0145287  -0.0088007
GX3   -0.0866941  -0.0150957   0.0945769  -0.0154627  -0.0093070
GY3   -0.0257505  -0.0142952   0.0895621   0.0013477  -0.0000466
GZ3    0.1613309   0.0895621  -0.5611216  -0.0084438   0.0002920
          GZ2         GX3         GY3         GZ3     
GZ2    0.0551377
GX3    0.0583102   0.1021568
GY3    0.0002920   0.0244027   0.0143418
GZ3   -0.0018293  -0.1528871  -0.0898540   0.5629509

ただし、最後の4行を上のデータの横の列に移動し、そのヘッダー(GZ2、GX3、GY3、GZ3)が他のヘッダーと同じ行になるように移動しようとしています。簡単に言えば、結果の出力は、各列と行のラベル付き9 * 9データ行列でなければなりません(下記参照)。

          GX1         GY1         GZ1         GX2         GY2         GZ2         GX3         GY3         GZ3
GX1    0.6941232
GY1    0.0187624   0.0156533
GZ1   -0.1175495  -0.0980708   0.6144300
GX2   -0.6074291  -0.0036667   0.0229726   0.6228918
GY2    0.0069881  -0.0013581   0.0085087   0.0023190   0.001404
GZ2   -0.0437815   0.0085087  -0.0533084  -0.0145287  -0.0088007   0.0551377
GX3   -0.0866941  -0.0150957   0.0945769  -0.0154627  -0.0093070   0.0583102   0.1021568
GY3   -0.0257505  -0.0142952   0.0895621   0.0013477  -0.0000466   0.0002920   0.0244027   0.0143418
GZ3    0.1613309   0.0895621  -0.5611216  -0.0084438   0.0002920  -0.0018293  -0.1528871  -0.0898540   0.5629509

ベストアンサー1

単純なPerlスクリプトはこれをうまく行います(Perlはほぼどこにでもインストールされます)。

#!/usr/bin/env perl

my @rows; # Preserve order of appearance
my %rows;

my $heading;

for (<>) {
    chomp;
    if (s/^\s+/   /) {
        $heading .= $_;
    } elsif (/^(\w+) (.*)$/) {
        push @rows, $1 if not exists $rows{$1};
        $rows{$1} .= $2;
    } else {
        die "Invalid line format at line $.";
    }
}
my $fmt = "%-5s %s\n"; # Adjust width to suit taste
printf $fmt, '', $heading;
printf $fmt, $_, $rows{$_} for @rows;

次のようにデータを使用してプログラムを呼び出すだけです。

$ my_column.pl < your_data.txt

(もちろん、上記のスクリプトを別の名前で保存しmy_column.plて実行可能にするものとします。chmod 755 my_column.pl

上記の作業を実行する必要がありますが、正確な列ソートまたは高度な書式設定が必要な場合は、Perlで使用できる多くのテーブル書式設定モジュールの1つを使用して列を設定し、特定splitの列幅を強制できます。printf

おすすめ記事