如何解决bash将文件中的所有数字乘以一个常数
我有一个包含单词和数字的文件。我想使用一些bash命令将该文件中的所有数字乘以一个常数。
我的文件如下:
192
TotEnergy=-1103.24236000 cutoff=-1.00000000 nneightol=1.20000000 pbc="T T T" Lattice="23.46511000 0.00000000 0.00000000 -0.00000100 23.46511000 0.00000000 -0.00000100 -0.00000100 23.46511000" Properties=species:S:1:pos:R:3:force:R:3:Z:I:1
O 11.72590000 14.59020000 25.33440000 -0.04213780 0.03788820 0.00314949 8
H 12.69400000 16.13880000 24.72010000 -0.03709700 -0.03453660 0.01566490 1
H 9.70021000 15.03790000 25.76530000 0.07676920 -0.00101183 -0.02270490 1
O 10.68010000 3.41217000 4.43292000 -0.01918440 0.01516070 0.03966070 8
H 10.14500000 3.90822000 6.40047000 0.01092440 -0.00643783 -0.08715890 1
H 9.97507000 4.53606000 3.00742000 0.01153240 -0.01693960 0.04267200 1
O -1.28237000 20.66930000 0.33214000 0.01567000 0.05712230 -0.02019150 8
我的主要目的是将以O或H开头的行的前三列相乘。但是,将所有数字相乘也是可以的,并且很容易处理。
常数= 2的预期输出
192
TotEnergy=-1103.24236000 cutoff=-1.00000000 nneightol=1.20000000 pbc="T T T" Lattice="23.46511000 0.00000000 0.00000000 -0.00000100 23.46511000 0.00000000 -0.00000100 -0.00000100 23.46511000" Properties=species:S:1:pos:R:3:force:R:3:Z:I:1
O 23.45180000 29.18040000 50.66880000 -0.04213780 0.03788820 0.00314949 8
.
.
.
(similarly for other lines)
可以使用哪种bash命令来完成此操作?
解决方法
可能的解决方案(请谨慎,因为您的问题缺少预期的输出以及您尝试过的操作的详细信息。)
打开文本编辑器,然后将以下脚本另存为colmult
:
#!/usr/bin/env -S awk -f
BEGIN{
# If constant m not provided,default to 10
if (m==0) {
m=10
}
}
{
# If first column is O or H
if ($1 ~ /^[OH]$/) {
for (c=2; c<=4; c++) {
$c*=m # multiply column by constant m
$c=sprintf("%.8f",$c) # format column's number
}
}
print # printout the line
}
使colmult
可执行。
带有Linux shell的示例:
chmod +x colmult
然后使用此脚本命令将inputfile
的前三列乘以一个常数(在这里我将乘数选择为42.666
作为一个任意示例) :
./colmult -v m=42.666 inputfile
以下是使用上述awk脚本处理示例数据的输出:
192
TotEnergy=-1103.24236000 cutoff=-1.00000000 nneightol=1.20000000 pbc="T T T" Lattice="23.46511000 0.00000000 0.00000000 -0.00000100 23.46511000 0.00000000 -0.00000100 -0.00000100 23.46511000" Properties=species:S:1:pos:R:3:force:R:3:Z:I:1
O 500.29724940 622.50547320 1080.91751040 -0.04213780 0.03788820 0.00314949 8
H 541.60220400 688.57804080 1054.70778660 -0.03709700 -0.03453660 0.01566490 1
H 413.86915986 641.60704140 1099.30228980 0.07676920 -0.00101183 -0.02270490 1
O 455.67714660 145.58364522 189.13496472 -0.01918440 0.01516070 0.03966070 8
H 432.84657000 166.74811452 273.08245302 0.01092440 -0.00643783 -0.08715890 1
H 425.59633662 193.53553596 128.31458172 0.01153240 -0.01693960 0.04267200 1
O -54.71359842 881.87635380 14.17108524 0.01567000 0.05712230 -0.02019150 8
,
您可以为此使用强大的Perl:
$ perl -lape 'if (/^[OH]/) {for $i (1..3) {s/@F[$i]/sprintf("%.8f",@F[$i]*2)/e}}' file
打印:
192
TotEnergy=-1103.24236000 cutoff=-1.00000000 nneightol=1.20000000 pbc="T T T" Lattice="23.46511000 0.00000000 0.00000000 -0.00000100 23.46511000 0.00000000 -0.00000100 -0.00000100 23.46511000" Properties=species:S:1:pos:R:3:force:R:3:Z:I:1
O 23.45180000 29.18040000 50.66880000 -0.04213780 0.03788820 0.00314949 8
H 25.38800000 32.27760000 49.44020000 -0.03709700 -0.03453660 0.01566490 1
H 19.40042000 30.07580000 51.53060000 0.07676920 -0.00101183 -0.02270490 1
O 21.36020000 6.82434000 8.86584000 -0.01918440 0.01516070 0.03966070 8
H 20.29000000 7.81644000 12.80094000 0.01092440 -0.00643783 -0.08715890 1
H 19.95014000 9.07212000 6.01484000 0.01153240 -0.01693960 0.04267200 1
O -2.56474000 41.33860000 0.66428000 0.01567000 0.05712230 -0.02019150 8
或awk
:
$ awk '/^[OH]/ {for (i=2;i<=4;i++) $i=sprintf("%.8f",$i*2)} 1' file
如果要保持列间距,请回到Perl:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
open my $fh,'<','/tmp/file' or die "Can't open file $!";
my $factor=2;
my @range=(1..3);
while (<$fh>) {
chomp;
if (/^[OH]\h+/){
my @field=split(/(?<=\H)(?=\h+|$)/);
for my $i (@range) {
my @comp=split(/\./,$field[$i]);
my $decimals=length($comp[1]);
my $field_width=length($field[$i]);
my $new_num=sprintf("%.*f",$decimals,$field[$i]*$factor);
$field[$i]=sprintf(" %*s",$field_width-1,$new_num);
}
say join('',@field);
}
else {
say;
}
}
或使用gawk
(不是POSIX awk):
$ gawk -v factor=2 'BEGIN{FPAT="([OH])|(\\s+[-]?[0-9]+\\.[0-9]+)|(\\s+[0-9]+)"}
/^[OH]\s+/ {
for(i=2;i<=3;i++){
if (index($i,".")) {
split($i,a,"\\.")
decimal = length(a[2])
}
else
decimal=0
$i=sprintf("%*s",length($i)-1,sprintf("%.*f",decimal,$i*factor))
}
}
1' file
两个打印:
192
TotEnergy=-1103.24236000 cutoff=-1.00000000 nneightol=1.20000000 pbc="T T T" Lattice="23.46511000 0.00000000 0.00000000 -0.00000100 23.46511000 0.00000000 -0.00000100 -0.00000100 23.46511000" Properties=species:S:1:pos:R:3:force:R:3:Z:I:1
O 23.45180000 29.18040000 50.66880000 -0.04213780 0.03788820 0.00314949 8
H 25.38800000 32.27760000 49.44020000 -0.03709700 -0.03453660 0.01566490 1
H 19.40042000 30.07580000 51.53060000 0.07676920 -0.00101183 -0.02270490 1
O 21.36020000 6.82434000 8.86584000 -0.01918440 0.01516070 0.03966070 8
H 20.29000000 7.81644000 12.80094000 0.01092440 -0.00643783 -0.08715890 1
H 19.95014000 9.07212000 6.01484000 0.01153240 -0.01693960 0.04267200 1
O -2.56474000 41.33860000 0.66428000 0.01567000 0.05712230 -0.02019150 8
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。