Bash嵌套循环读取CSV时仅执行一轮for循环问题排查
问题:Bash脚本仅执行一轮while循环后终止
现有一段Bash脚本,逻辑无错误,但仅能执行一轮while循环(遍历完ratio数组后即终止),而regime.csv包含30行4列数据。
存在问题的脚本
#!/bin/bash csv_file="regime.csv" ratio=(0.2 0.4 0.6 0.8) while IFS=',' read -r col1 col2 col3 col4; do echo $col1 echo $col2 echo $col3 echo $col4 for rat in "${ratio[@]}"; do dir_name="${col4}_T${col1}_erate${col2}_${rat}" mkdir -p "$dir_name" cp in.C3N run.sh BNC.tersoff data_C3N.txt "$dir_name/" sed -i "s/\(variable[[:space:]]\+T equal \).*/\1${col1}/" "$dir_name/in.C3N" sed -i "s/\(variable[[:space:]]\+erate equal \).*/\1${col2}/" "$dir_name/in.C3N" sed -i "s/\(variable[[:space:]]\+reg equal \).*/\1${rat}/" "$dir_name/in.C3N" sed -i "s/\(variable[[:space:]]\+time equal \).*/\1${col3}/" "$dir_name/in.C3N" if [ "$col4" = "ZZ" ]; then sed -i '/^fix[[:space:]]\+deform Boundary deform 1 y erate/{ N s/\(fix.* y erate.*\)\n\(fix.* x erate.*\)/\2\n\1/ }' "$dir_name/in.C3N" fi # Change into the new directory, run run.sh, and return to the parent folder. pushd "$dir_name" > /dev/null ./run.sh popd > /dev/null done done < "$csv_file"
可正常运行的对比示例脚本
#!/usr/bin/env bash file="test.txt" a=(1 2 3) while IFS=' ' read -r col1 col2 rest; do for val in "${a[@]}"; do echo "$col1 $col2 and $val" done done < "$file"
排查过程更新
更新1:CSV文件格式验证
regime.csv在Ubuntu的Jupyter-notebook中创建,前5行的cat -A输出如下:
cat -A regime.csv | head -5 100,0.01,978,AC$ 1500,0.01,338,AC$ 300,0.01,780,AC$ 1000,0.01,425,AC$ 1500,0.001,2901,AC$
更新2:run.sh内容
完整运行需要LAMMPS,也可将mpirun行替换为echo命令测试:
#!/bin/bash LAMMPS_EXECUTABLE='/home/km9mb/Downloads/lammps-29Aug2024/src/lmp_mpi' INPUT_FILE="in.C3N" mpirun --oversubscribe -np 32 ${LAMMPS_EXECUTABLE} -in ${INPUT_FILE}
更新3:定位问题根源
注释掉脚本中的./run.sh后,脚本可以正常执行完所有CSV行,确认问题出在run.sh的执行上。
解决方法
在run.sh的mpirun命令中添加--stdin none参数,修改后的命令如下:
mpirun --stdin none --oversubscribe -np 32 ${LAMMPS_EXECUTABLE} -in ${INPUT_FILE}
原因说明:mpirun默认会继承父进程的标准输入,导致while循环读取CSV的输入流被抢占,循环提前终止。添加--stdin none参数后,mpirun不再占用标准输入,while循环可以正常读取完CSV的所有行。
内容的提问来源于stack exchange,提问作者Karen Tabar
相关产品推荐
相关产品推荐

