如何在不影响文件格式的情况下更改文本文件中的行数组
How to change a array of rows in a text file without disturbing the format of the file
我有一个 DFT 代码 (VASP) 的输入文件 POSCAR,如下所示:
System
1.00000000000000
**5.2916193007999999 0.0000000000000000 0.0000000000000000
0.0000000000000000 5.2916193007999999 0.0000000000000000
0.0000000000000000 0.0000000000000000 20.0097122192000008**
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
我想变形,或者我想说,我想更改一些具有特定百分比的参数,比如 0.5%,(这些以粗体显示)。
我们可以将粗体参数的数组命名为:
a11 a12 a13
a21 a22 a23
a31 a32 a33
根据具体情况,我需要将a11修改为a33(有时可能只有a11或a11修改为a13或全部为a)变形+0.5%,变形-0.5%
我的作业文件中需要一个 shell (bash) 脚本,以便生成所需的变形数据文件。
最终数据应该在两个目录中减去(它将有 a-a0.005)和加号((它将有 a+a0.005)。
最终数据应该是这样的:
在plus(mkdir plus)目录下,POSCAR文件应该是这个:
System
1.00000000000000
5.3180773973039998995 1.0050000000000000000 1.4925000000000000000
1.0050000000000000000 5.3180773973039998995 0.2010000000000000000
1.4925000000000000000 0.2010000000000000000 10.0500000000000000000
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
在minus(mkdir minus)目录下,POSCAR文件应该是这个:
System
1.00000000000000
5.2651612042959999005 0.9950000000000000000 1.4925000000000000000
0.9950000000000000000 5.2651612042959999005 0.1990000000000000000
1.4925000000000000000 0.1990000000000000000 9.9500000000000000000
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
重要的是,直接下面出现的所有行都不会发生变化。
我正在尝试如下使用
#!/bin/bash
DEFORM=0.005
A11=$(cat POSCAR | head -n 3 | tail -n 1 | awk '{print }')
A12=$(cat POSCAR | head -n 3 | tail -n 1 | awk '{print }')
A13=$(cat POSCAR | head -n 3 | tail -n 1 | awk '{print }')
A21=$(cat POSCAR | head -n 4 | tail -n 1 | awk '{print }')
A22=$(cat POSCAR | head -n 4 | tail -n 1 | awk '{print }')
A23=$(cat POSCAR | head -n 4 | tail -n 1 | awk '{print }')
A31=$(cat POSCAR | head -n 5 | tail -n 1 | awk '{print }')
A32=$(cat POSCAR | head -n 5 | tail -n 1 | awk '{print }')
A33=$(cat POSCAR | head -n 5 | tail -n 1 | awk '{print }')
PA11=$(echo "$A11" "$DEFORM" | awk '{printf "%.16f\n", +*}')
sed -i "s/$A11/$PA11/g" POSCAR
但这似乎是一个艰难的过程。我正在寻找一个简单的脚本。
我不熟悉这种文件格式,所以你得自己检查一下。
就awk而言,创建一个脚本(poscar.awk):
BEGIN{ DEFORM=0.005 }
NR>=3 && NR<=5{
=-DEFORM
=-DEFORM
=-DEFORM
printf " %.16f %.16f %.16f\n", , , # This prints lines 3-5
}
!(NR>=3 && NR<=5) # This prints all other lines
然后您可以:awk -f poscar.awk inputfile
这将导致:
System
1.00000000000000
5.2866193008000000 0.9950000000000000 1.4950000000000001
3.9950000000000001 5.2866193008000000 0.1950000000000000
2.9950000000000001 0.2950000000000000 9.9949999999999992
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
这可能是您正在尝试做的事情:
$ cat tst.awk
NR==1 {
plus = FILENAME "_plus"
minus = FILENAME "_minus"
}
(3 <= NR) && (NR <= 5) {
for (i=1; i<=NF; i++) {
printf "%0.16f%s", $i * 1.005, (i<NF ? OFS : ORS) > plus
printf "%0.16f%s", $i * 0.095, (i<NF ? OFS : ORS) > minus
}
next
}
{
print > plus
print > minus
}
$ awk -f tst.awk file
$ head -100 file_*
==> file_minus <==
System
1.00000000000000
0.5027038335760000 0.0000000000000000 0.0000000000000000
0.0000000000000000 0.5027038335760000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.9009226608240002
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
==> file_plus <==
System
1.00000000000000
5.3180773973039992 0.0000000000000000 0.0000000000000000
0.0000000000000000 5.3180773973039992 0.0000000000000000
0.0000000000000000 0.0000000000000000 20.1097607802959999
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
我有一个 DFT 代码 (VASP) 的输入文件 POSCAR,如下所示:
System
1.00000000000000
**5.2916193007999999 0.0000000000000000 0.0000000000000000
0.0000000000000000 5.2916193007999999 0.0000000000000000
0.0000000000000000 0.0000000000000000 20.0097122192000008**
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
我想变形,或者我想说,我想更改一些具有特定百分比的参数,比如 0.5%,(这些以粗体显示)。 我们可以将粗体参数的数组命名为:
a11 a12 a13
a21 a22 a23
a31 a32 a33
根据具体情况,我需要将a11修改为a33(有时可能只有a11或a11修改为a13或全部为a)变形+0.5%,变形-0.5%
我的作业文件中需要一个 shell (bash) 脚本,以便生成所需的变形数据文件。
最终数据应该在两个目录中减去(它将有 a-a0.005)和加号((它将有 a+a0.005)。
最终数据应该是这样的:
在plus(mkdir plus)目录下,POSCAR文件应该是这个:
System
1.00000000000000
5.3180773973039998995 1.0050000000000000000 1.4925000000000000000
1.0050000000000000000 5.3180773973039998995 0.2010000000000000000
1.4925000000000000000 0.2010000000000000000 10.0500000000000000000
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
在minus(mkdir minus)目录下,POSCAR文件应该是这个:
System
1.00000000000000
5.2651612042959999005 0.9950000000000000000 1.4925000000000000000
0.9950000000000000000 5.2651612042959999005 0.1990000000000000000
1.4925000000000000000 0.1990000000000000000 9.9500000000000000000
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
重要的是,直接下面出现的所有行都不会发生变化。
我正在尝试如下使用
#!/bin/bash
DEFORM=0.005
A11=$(cat POSCAR | head -n 3 | tail -n 1 | awk '{print }')
A12=$(cat POSCAR | head -n 3 | tail -n 1 | awk '{print }')
A13=$(cat POSCAR | head -n 3 | tail -n 1 | awk '{print }')
A21=$(cat POSCAR | head -n 4 | tail -n 1 | awk '{print }')
A22=$(cat POSCAR | head -n 4 | tail -n 1 | awk '{print }')
A23=$(cat POSCAR | head -n 4 | tail -n 1 | awk '{print }')
A31=$(cat POSCAR | head -n 5 | tail -n 1 | awk '{print }')
A32=$(cat POSCAR | head -n 5 | tail -n 1 | awk '{print }')
A33=$(cat POSCAR | head -n 5 | tail -n 1 | awk '{print }')
PA11=$(echo "$A11" "$DEFORM" | awk '{printf "%.16f\n", +*}')
sed -i "s/$A11/$PA11/g" POSCAR
但这似乎是一个艰难的过程。我正在寻找一个简单的脚本。
我不熟悉这种文件格式,所以你得自己检查一下。
就awk而言,创建一个脚本(poscar.awk):
BEGIN{ DEFORM=0.005 }
NR>=3 && NR<=5{
=-DEFORM
=-DEFORM
=-DEFORM
printf " %.16f %.16f %.16f\n", , , # This prints lines 3-5
}
!(NR>=3 && NR<=5) # This prints all other lines
然后您可以:awk -f poscar.awk inputfile
这将导致:
System
1.00000000000000
5.2866193008000000 0.9950000000000000 1.4950000000000001
3.9950000000000001 5.2866193008000000 0.1950000000000000
2.9950000000000001 0.2950000000000000 9.9949999999999992
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
这可能是您正在尝试做的事情:
$ cat tst.awk
NR==1 {
plus = FILENAME "_plus"
minus = FILENAME "_minus"
}
(3 <= NR) && (NR <= 5) {
for (i=1; i<=NF; i++) {
printf "%0.16f%s", $i * 1.005, (i<NF ? OFS : ORS) > plus
printf "%0.16f%s", $i * 0.095, (i<NF ? OFS : ORS) > minus
}
next
}
{
print > plus
print > minus
}
$ awk -f tst.awk file
$ head -100 file_*
==> file_minus <==
System
1.00000000000000
0.5027038335760000 0.0000000000000000 0.0000000000000000
0.0000000000000000 0.5027038335760000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.9009226608240002
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216
==> file_plus <==
System
1.00000000000000
5.3180773973039992 0.0000000000000000 0.0000000000000000
0.0000000000000000 5.3180773973039992 0.0000000000000000
0.0000000000000000 0.0000000000000000 20.1097607802959999
Ta N
2 4
Direct
0.0000000000000000 0.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000
0.1430930929177486 0.6430931269177513 0.5336780085877783
0.8569068730822487 0.3569069180822488 0.5336780085877783
0.6430931269177513 0.8569068730822487 0.4663219914122216
0.3569069180822488 0.1430930929177486 0.4663219914122216