Bash中遍历数值列表时如何通过sed命令正确替换文件内容
问题根因
你写的脚本跑不通有三个直接问题:
- sed是纯文本替换工具,本身不做算术运算,你在替换串里写
k+96只会原样写入文件,不会自动算出数值和。 - 你的匹配规则是固定找
seed=k+rank字符串,第一次替换完文件里的行已经变成seed=1+96+rank,后续循环根本匹配不到目标内容,迭代直接断了。 - 替换规则里多写了一层外层大括号,和你Fortran源码里的实际行格式不匹配,从一开始匹配逻辑就有误差。
可行实现
给两种稳定方案,优先推荐第二种,从根源上避免反复改源码带来的问题。
方案1:保留sed改源码的逻辑,修正替换规则
首先先把你的main.f90里对应行改回初始状态seed=k+rank,删掉之前替换错的内容,然后用下面的脚本:
# 配置参数 step=96 k_max=961 # C风格for循环直接按步长生成k值,比大括号生成序列更适配变量计算 for ((k=1; k<=k_max; k+=step)); do # 先把上一轮修改过的行还原回初始模板,保证每次匹配都能命中 sed -i "s/^seed=.*+rank$/seed=k+rank/" main.f90 # bash里提前算好当前k的数值,直接替换成最终的常量表达式 sed -i "s/^seed=k+rank$/seed=${k}+rank/" main.f90 # 替换成你的实际程序运行命令 sleep 15m done # 循环结束后把源码还原回初始状态 sed -i "s/^seed=.*+rank$/seed=k+rank/" main.f90
这里给sed的匹配规则加了行首^和行尾$锚定,避免误替换文件里其他位置的相似字符串。
方案2:优化Fortran代码逻辑,不需要每次改源码
反复sed修改源码很容易因为匹配失误把源文件改坏,更合理的做法是把k做成程序运行时的入参,根本不需要动源码:
首先修改Fortran代码,支持读取命令行传入的k值:
program main implicit none integer :: rank, seed, k, arg_cnt character(len=32) :: cmd_arg ! 读取命令行传入的第一个参数作为k arg_cnt = command_argument_count() if (arg_cnt < 1) then print *, "Error: 请传入k参数" stop 1 end if call get_command_argument(1, cmd_arg) read(cmd_arg, *) k ! 原有rank赋值逻辑 seed = k + rank ! 其余你的业务逻辑 end program
对应的shell脚本逻辑会简单很多,完全不需要sed操作:
step=96 k_max=961 for ((k=1; k<=k_max; k+=step)); do # 直接把k作为参数传给编译好的可执行文件 ./your_program $k sleep 15m done
注意:所有需要做算术计算的逻辑都要在bash层通过
$((表达式))或者C风格for循环提前算好,sed只负责把你给的确定字符串写到对应位置,不要让sed承担计算逻辑。
内容的提问来源于stack exchange,提问作者ferro11001
相关产品推荐
相关产品推荐

