![如何将一行中的文本附加到另一行的末尾?](https://linux22.com/image/100506/%E5%A6%82%E4%BD%95%E5%B0%86%E4%B8%80%E8%A1%8C%E4%B8%AD%E7%9A%84%E6%96%87%E6%9C%AC%E9%99%84%E5%8A%A0%E5%88%B0%E5%8F%A6%E4%B8%80%E8%A1%8C%E7%9A%84%E6%9C%AB%E5%B0%BE%EF%BC%9F.png)
原始输出文件包含此文本块以及更多信息:
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
但是,我试图移动最后四行,以便它们位于上面数据旁边的列中,其各自的标题(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 可用的许多表格格式化模块之一split
来设置列并强制特定的列宽。printf
答案2
设法解决我自己的问题,只需将特定的行和列分配为变量,并使用 echo 连接它们,当您知道答案时就很简单!
#!/bin/bash
cd FREQ/HF
rm Hessian.log
for i in *.out
do
grep -H -A16 "Force Constants (Second Derivatives of the Energy)" $i | tail -n +1 >> Hessian.tmp
x=`awk ' NR == 2 {printf " "" %10s %10s %10s %10s %10s \n", $2,$3,$4,$5,$6}' Hessian.tmp`
y=`awk ' NR == 12 {printf "%10s %10s %10s %10s \n", $2,$3,$4,$5}' Hessian.tmp`
a=`awk ' NR == 8 { printf "%5s %10s %10s %10s %10s %10s\n", $2,$3,$4,$5,$6,$7} ' Hessian.tmp`
b=`awk ' NR == 9 { printf "%5s %10s %10s %10s %10s %10s\n", $2,$3,$4,$5,$6,$7} ' Hessian.tmp`
c=`awk ' NR == 10 { printf "%5s %10s %10s %10s %10s %10s\n", $2,$3,$4,$5,$6,$7} ' Hessian.tmp`
d=`awk ' NR == 11 { printf "%5s %10s %10s %10s %10s %10s\n", $2, $3,$4,$5,$6,$7} ' Hessian.tmp`
e=`awk ' NR == 13 { printf "%10s", $3} ' Hessian.tmp`
f=`awk ' NR == 14 { printf "%10s %10s", $3, $4} ' Hessian.tmp`
g=`awk ' NR == 15 { printf "%10s %10s %10s", $3, $4,$5} ' Hessian.tmp`
h=`awk ' NR == 16 { printf "%10s %10s %10s %10s", $3, $4, $5,$6} ' Hessian.tmp`
echo "$x $y" >> Hessian.log
awk '
NR == 3, NR == 7 {printf "%5s %10s %10s %10s %10s %10s\n", $2,$3,$4,$5,$6,$7} ' Hessian.tmp >> Hessian.log
echo "$a $e" >> Hessian.log
echo "$b $f" >> Hessian.log
echo "$c $g" >> Hessian.log
echo "$d $h" >> Hessian.log
rm Hessian.tmp
echo "" >> Hessian.log
done