编写Bash脚本提取喷雾模拟各时间步vaporpenetrationlength数据
前置约定
脚本默认适配仿真程序的通用输出规则,如果你本地文件结构不一样,只需要改后面提到的配置项即可:
- 所有时间步文件夹都放在同一级目录下,文件夹名本身就是对应的时间值(比如
0.001s、2.5ms这类命名) - 每个时间步文件夹内存储质量分数数据的文件名固定,文件内容按行存储:每行两个数值,第一列为距离喷油器的长度值,第二列为对应位置的蒸汽质量分数,且数据按距离从小到大排序(距离喷油器越近,质量分数越高,越远则越低)
逐行构建脚本+代码解释
你可以逐行把下面的内容写到后缀为.sh的脚本文件里,每一行的作用都附了说明:
- 第一行固定写解释器声明
#!/bin/bash
这是所有bash脚本的标准开头,告诉操作系统这个文件要用bash程序解析执行,必须放在脚本的第一行。
- 第二部分写可配置参数,后续改规则只需要动这部分
# 目标质量分数:0.1% 转成小数为0.001 TARGET_MASS_FRACTION=0.001 # 每个时间步文件夹内存储质量分数数据的文件名,按你本地实际文件名改 DATA_FILENAME="mass_fraction.dat"
把后续逻辑里要用到的固定值提前定义成变量,后续如果要改目标阈值、改数据文件名,只需要修改这两个值就行,不用翻后面的业务逻辑;
#开头的内容是注释,脚本运行时不会执行。
- 打印结果表头,方便后续直接导成表格画图
echo "time_step,vapor_penetration_length"
echo是shell里最基础的打印命令,会把后面跟的文本输出到终端;这里打印的表头两列分别对应时间步、蒸汽穿透长度,后续把输出存成csv文件可以直接导入Origin、Matplotlib等工具绘图。
- 写循环头,遍历当前目录下所有时间步文件夹
for time_dir in */; do
这是for循环的起始标记:
*/是shell通配符,会自动匹配当前目录下的所有子文件夹,每一轮循环都会把一个文件夹的路径赋值给time_dir变量;do标记循环体的开始,后面的所有逻辑都会对每个文件夹执行一遍。
- 从文件夹路径里提取干净的时间步值
time_step=$(basename "$time_dir")
这里的
$( )语法作用是:把括号内命令的运行结果存到左边的变量里;basename命令会自动把路径末尾的文件夹名单独抠出来,去掉路径自带的末尾斜杠,比如time_dir的值是0.002s/,处理后就得到干净的时间值0.002s;变量两边套双引号是写shell脚本的通用好习惯,能避免文件夹名带空格、特殊字符时脚本运行报错。
- 拼接当前时间步下数据文件的完整路径
data_file="${time_dir}${DATA_FILENAME}"
把文件夹路径和之前定义的数据文件名拼起来,比如当前处理的文件夹是
0.001ms/,拼接后得到的data_file值就是0.001ms/mass_fraction.dat,也就是我们要读取的目标文件路径。
- 加容错判断:如果当前文件夹里没找到数据文件,就跳过不处理
if [ ! -f "$data_file" ]; then echo "警告:$time_dir 下未找到对应数据文件,跳过" >&2 continue fi
这是if条件判断:
-f用来判断后面跟的路径是不是存在的普通文件,前面加!是取反,也就是“如果目标数据文件不存在”的话,就执行内部逻辑:打印警告信息(>&2的作用是把警告信息输出到错误流,不会混进前面的正常结果表格里),然后用continue跳过当前文件夹的后续处理,直接进入下一轮循环。
- 核心逻辑:从数据文件里找质量分数为0.1%对应的距离值
penetration_length=$(awk -v target="$TARGET_MASS_FRACTION" '$2 <= target {print $1; exit}' "$data_file")
这里用
awk工具处理文本数据,它是shell里专门处理行列格式文本的工具,读大文件速度非常快,适合处理仿真输出的大体积数据文件:
-v target="$TARGET_MASS_FRACTION":把我们之前定义的目标质量分数值传给awk内部使用'$2 <= target {print $1; exit}':逐行读取数据文件,判断第二列(也就是质量分数列)的值是否小于等于目标阈值,一旦找到符合条件的行,就打印第一列(也就是距离值),然后立刻退出awk不用读后面的内容,效率很高- 最终把awk输出的距离值存到
penetration_length变量里,也就是我们要的蒸汽穿透长度。
- 再加一层容错:如果数据里没找到符合阈值的位置,就跳过
if [ -z "$penetration_length" ]; then echo "警告:$time_step 对应数据中未找到质量分数≤0.1%的位置,跳过" >&2 continue fi
-z用来判断变量内容是不是为空,如果awk遍历完整个文件都没找到符合条件的行,penetration_length就会是空值,这时候打印警告跳过即可,避免输出无效数据。
- 打印当前时间步对应的计算结果
echo "${time_step},${penetration_length}"
把时间步和对应的穿透长度按逗号分隔打印,和最开始打印的表头格式对应。
- 最后一行标记循环结束
done
脚本使用步骤
- 把上面写好的内容保存成
extract_penetration.sh文件,放到所有时间步文件夹的同级目录下 - 打开终端,进入脚本所在目录,给脚本加执行权限:
chmod +x extract_penetration.sh - 运行脚本并把结果存到csv文件:
./extract_penetration.sh > penetration_result.csv - 生成的
penetration_result.csv可以直接导入各类绘图工具,不需要额外整理格式
适配提示:如果你的数据文件列顺序是第一列存质量分数、第二列存距离,只需要把awk那行里的
$1和$2互换即可;如果你的数据是按距离从大到小排序的,就把awk里的判断条件改成$2 >= target。
内容的提问来源于stack exchange,提问作者hulk99

