简介
最近发现很多小伙伴该程序参数的时候在手动改,路径复杂的时候费时费力,改完还需要再重新编译运行非常麻烦。
这里介绍一种用shell脚本自动改参数并编译运行的方法。
shell 脚本
脚本:本质是一个文件,文件里面存放的是 特定格式的指令,系统可以使用脚本解析器 翻译或解析 指令 并执行(它不需要编译)
shell 既是应用程序 又是一种脚本语言。
Linux三剑客
Linux 三剑客是(grep,sed,awk)三者的简称,他们通常结合正则一起使用。
grep擅长查找,sed擅长修改文件。awk擅长取列。
给一个链接: Linux三剑客自行了解
这里我直接讲重点 sed -i命令
sed 命令
# 对每行匹配到的第一个字符串进行替换
sed -i 's/原字符串/新字符串/' a.txt
# 对全局匹配上的所有字符串进行替换
sed -i 's/原字符串/新字符串/g' a.txt
# 删除所有匹配到字符串的行
sed -i '/匹配字符串/d' a.txt
# 特定字符串的行后插入新行
sed -i '/特定字符串/a 新行字符串' a.txt
# 特定字符串的行前插入新行
sed -i '/特定字符串/i 新行字符串' a.txt
# 把匹配行中的某个字符串替换为目标字符串
sed -i '/匹配字符串/s/源字符串/目标字符串/g' a.txt
# 在文件ab.txt中的末行之后,添加bye
sed -i '$a bye' a.txt
# 对于文件第3行,把匹配上的所有字符串进行替换
sed -i '3s/原字符串/新字符串/g' a.txt
介绍具体用法。比如我要改 ./system/controlDict 里的 endtime 参数。
文件内容如下
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 2.1.1 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application twoPhaseEulerFoam;
startFrom startTime;
stopAt endTime;
startTime 0.0;
endTime 10.01; // 要修改的参数
writeControl timeStep;
writeInterval 1000;
deltaT 1.0e-3;
purgeWrite 0;
writeFormat ascii;
//writeFormat binary;
writePrecision 6;
writeCompression uncompressed;
timeFormat general;
timePrecision 9;
runTimeModifiable on;
maxCo 1;
maxDeltaT 1e-05;
// ************************************************************************* //
我们可以先用sed命令查看目标行。
# -n p 在终端显示, ^匹配开头 匹配 ./system/controlDict文件中以endTime开头的行
sed -n '/^endTime/p' ./system/controlDict
#输出结果:
#endTime 10.01;
# 或grep命令可以显示行号
grep -n '^endTime' ./system/controlDict
#输出结果:
#27:endTime 10.01;
再用sed -i 命令改
#先看看改的对不对
sed -n '27s/.*/endTime 20.01;/p' ./system/controlDict
#输出: endTime 20.01;
#改对了
#真改了
sed -i '27s/.*/endTime 20.01;/g' ./system/controlDict
sed -n '/^endTime/p' ./system/controlDict
#输出结果:
#endTime 20.01;
Shell 传递参数
那有同学又要问了,我这样写代码改不还的是手动改命令里的参数吗?
问得好,介绍一个高级命令
#!/bin/bash
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
为脚本设置可执行权限,并执行脚本,输出结果如下所示:
$ chmod +x test.sh
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3
相信聪明的同学已经领悟到了。
下面我们写一个同时改writeInterval和endTime两个参数的脚本。
#!/bin/bash
#change_parameters.sh
echo "执行的文件名:$0";
echo "endTime参数改为:$1";
sed -i '27s/.*/endTime '$1'.01;/g' ./system/controlDict
sed -n '27,27p' ./system/controlDict
echo "writeInterval参数改为:$2";
sed -i '30s/.*/writeInterval '$2';/g' ./system/controlDict
sed -n '30,30p' ./system/controlDict
为脚本设置可执行权限,并执行脚本,输出结果如下所示:
$ chmod +x change_parameters.sh
$ ./change_parameters.sh 20 500
执行的文件名:./change_parameters.sh
endTime参数改为:20
endTime 20.01;
writeInterval参数改为:500
writeInterval 500;
那喜欢思考的同学又要问了,还有没有更牛逼的改法呀?
有,加上正则表达式,awk grep sed 命令基本可以满足任意的修改需求。有需要可以评论区留言。
后续我会推出更高级的教程,结合paraview的python脚本,可以实现cfd程序自动后处理。
重新编译 运行
本质就是把手动操作写在一起。以cfd为例,改完参数后需要重新划分进程,编译,运行。
rm process* -r
blockMesh
./clean.sh
decomposePar
rm *.log *.dat *.xyz
mpirun -np 12 ./Solver -parallel 2>&1 | tee 1.log