Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash awk:如何在M行中每隔N行添加一个常数?_Bash_Shell_Perl_Awk_Sed - Fatal编程技术网

Bash awk:如何在M行中每隔N行添加一个常数?

Bash awk:如何在M行中每隔N行添加一个常数?,bash,shell,perl,awk,sed,Bash,Shell,Perl,Awk,Sed,我目前在使用bash脚本编辑文件时遇到问题。它是一个包含数百个时间戳的一系列原子的笛卡尔坐标(x,y,z)的文件。对于由3个原子组成的系统,它如下所示: t=1 x y z O 1.2 1.5 0.8 H 0.4 2.3 1.3 H 1.3 2.5 1.1 t=2 x y z O 1.3 1.6 0.9 H 0.3 2.5 1.2 H 1.1 2.3 0.9 t=3 x y z O 1.2 1.8 1.0 H 0.5 2.2 1.1 H 1.5 2.

我目前在使用bash脚本编辑文件时遇到问题。它是一个包含数百个时间戳的一系列原子的笛卡尔坐标(x,y,z)的文件。对于由3个原子组成的系统,它如下所示:

t=1 x y z  
O 1.2 1.5 0.8  
H 0.4 2.3 1.3  
H 1.3 2.5 1.1  
t=2 x y z  
O 1.3 1.6 0.9  
H 0.3 2.5 1.2  
H 1.1 2.3 0.9  
t=3 x y z   
O 1.2 1.8 1.0  
H 0.5 2.2 1.1  
H 1.5 2.1 0.8  
t=4 x y z  
...
现在我想在4行中每3行的z坐标上加一个常数10。有人知道如何解决这个问题吗

我试过用awk。但是,它只能输出修改后的行。必须指出的是,我希望就地修改原始文件,而不仅仅是输出修改后的行

awk '{ if ((NR - 3) % 4 == 0) {$4=$4+10; print}}' file > outputfile
预期产出如下:

t=1 x y z  
O 1.2 1.5 0.8  
H 0.4 2.3 11.3  
H 1.3 2.5 1.1  
t=2 x y z   
O 1.3 1.6 0.9  
H 0.3 2.5 11.2  
H 1.1 2.3 0.9  
t=3 x y z  
O 1.2 1.8 1.0  
H 0.5 2.2 11.1  
H 1.5 2.1 0.8  
t=4 x y z   
...
现在我只得到:

H 0.4 2.3 11.3  
H 0.3 2.5 11.2  
H 0.5 2.2 11.1  
...

您只需稍微修改一下awk代码:

awk'{if(NR%4==3)$4=$4+10;print}'文件>输出文件

生成文件
outputfile
后,如果需要替换原始文件,只需运行
mv outputfile文件即可。

我想这就是您想要的(注意大括号外的打印)


保存
file.ORI
以防万一…

这里有一个使用Perl的解决方案:

perl -i -lape 'if ($. % 4 == 3) { $F[3] += 10; $_ = "@F" }' file
-i
开关使其(看起来)工作到位。使用
-i.bak
生成包含原始数据的
文件.bak

$。
存储当前行号<代码>$。%4==3
从每组4行中选择第3行<代码>$F[3]+=10将行的第四个字段增加10。

POSIX外壳解决方案:

#/副秘书长/垃圾箱/环境卫生
l=0#线路计数器
当读取-rhxyz时;读取一行并将每个字段存储在变量h x y z中
l=$((l+1))#增量行计数器
如果[$l-等式4];然后
#第四行包括标题=第三行数据
z=“$(echo“scale=1;$z+10”| bc)”#在z上加10
l=0#为下一个数据块重置行计数器
fi
回显“$h$x$y$z”#输出该行

完成与尝试计数记录和运行可能导致错误行增量的错误计数不同,您可以键入其中有
'='
符号的记录,然后从中使用计数器,例如

awk '/=/{n=0} n==2{$4+=10} {n++}1' file
解释

awk
表达式中使用了三条规则:

  • /=/{n=0}
    如果行包含
    '='
    设置计数器零
  • n==2{$4+=10}
    couter=
    2
    10
    递增第四个字段
  • {n++}
    递增计数器
最后的
1
是打印记录的默认值

示例使用/输出

$ awk '/=/{n=0} n==2{$4+=10} {n++}1' file
t=1 x y z
O 1.2 1.5 0.8
H 0.4 2.3 11.3
H 1.3 2.5 1.1
t=2 x y z
O 1.3 1.6 0.9
H 0.3 2.5 11.2
H 1.1 2.3 0.9
t=3 x y z
O 1.2 1.8 1.0
H 0.5 2.2 11.1
H 1.5 2.1 0.8
t=4 x y z
您可以重定向到新文件,然后根据需要覆盖原始文件。

这可能适合您(GNU-sed、bash和bc):


使用sed的module命令,从第3行开始,每隔4行使用
bc
将10添加到第4个字段。

NR%4==3{$4+=10}1
会更糟糕。同意@oguzismail:DSorry我太笨了,无法理解这个脚本。我找不到“每三行”的代码在哪里…我添加了注释
$ awk '/=/{n=0} n==2{$4+=10} {n++}1' file
t=1 x y z
O 1.2 1.5 0.8
H 0.4 2.3 11.3
H 1.3 2.5 1.1
t=2 x y z
O 1.3 1.6 0.9
H 0.3 2.5 11.2
H 1.1 2.3 0.9
t=3 x y z
O 1.2 1.8 1.0
H 0.5 2.2 11.1
H 1.5 2.1 0.8
t=4 x y z
sed -i '3~4{s/\S\+/$(echo "&+10"|bc -l)/4;s/.*/echo "&"/e}' file