如何在Shell脚本中单次调用radex,结合循环输入参数生成单个输出文件?
Radex批量计算Shell脚本优化方案
问题背景
需要批量运行radex程序计算物理参数,radex启动后会交互式请求输入文件名、输出文件、动力学温度等参数,计算完成后询问是否继续(输入1继续,0停止)。原脚本通过循环多次调用radex,每次用Here Document传入参数,最后输入0生成多个输出文件;但如果改为输入1想要合并为单个文件时失效,原因是每次循环都会启动新的radex进程,无法延续之前的会话。
解决方案
1. 仅调用一次radex完成批量计算
核心思路:一次性生成所有需要的交互式输入序列,通过管道传递给单个radex进程,实现单次启动完成所有计算。
#!/bin/bash index_array=(50 60 70) # 遍历数组生成完整输入流,最后一次计算后输入0停止 for i in "${index_array[@]}" do # 最后一个元素对应停止标志0,其余为1 stop_flag=$([ "$i" = "${index_array[-1]}" ] && echo 0 || echo 1) cat <<EOF CF_all_coll.dat Testy2.dat 200 210 $i 1 H2 100 2.73 3e12 1 $stop_flag EOF done | ./radex
2. 区分输入内容与循环代码
通过封装固定输入为函数,将循环逻辑与radex所需的输入内容分离,提升脚本可读性和维护性:
#!/bin/bash index_array=(50 60 70) # 封装radex固定输入模板,仅暴露可变参数和停止标志 generate_radex_input() { local var_param=$1 local stop_flag=$2 cat <<-INPUT_CONTENT CF_all_coll.dat Testy2.dat 200 210 $var_param 1 H2 100 2.73 3e12 1 $stop_flag INPUT_CONTENT } # 生成完整输入流并传递给radex for i in "${index_array[@]}" do if [ "$i" = "${index_array[-1]}" ]; then generate_radex_input "$i" 0 else generate_radex_input "$i" 1 fi done | ./radex
3. 其他可行的参数输入方式
方式一:预先生成参数文件再导入
先将所有输入内容写入临时文件,再将文件作为radex的输入源,方便调试和修改:
#!/bin/bash index_array=(50 60 70) # 创建临时文件存储输入参数 temp_input=$(mktemp) for i in "${index_array[@]}" do stop_flag=$([ "$i" = "${index_array[-1]}" ] && echo 0 || echo 1) # 将参数追加到临时文件 cat >> "$temp_input" <<EOF CF_all_coll.dat Testy2.dat 200 210 $i 1 H2 100 2.73 3e12 1 $stop_flag EOF done # 执行radex并传入参数文件 ./radex < "$temp_input" # 清理临时文件 rm "$temp_input"
方式二:使用expect脚本控制交互
如果radex的交互提示有明确特征,可使用expect工具更灵活地控制会话流程(需先安装expect):
#!/usr/bin/expect set index_array {50 60 70} set radex_path "./radex" # 启动radex进程 spawn $radex_path foreach i $index_array { # 匹配输入文件名提示,发送对应参数 expect "Enter input filename:" send "CF_all_coll.dat\r" # 匹配输出文件名提示 expect "Enter output filename:" send "Testy2.dat\r" # 匹配动力学温度提示 expect "Enter kinetic temperature(s):" send "200 210\r" # 匹配可变参数提示(需根据radex实际提示修改) expect "Enter column density:" send "$i\r" # 发送固定参数 send "1\r" send "H2\r" send "100\r" send "2.73\r" send "3e12\r" send "1\r" # 最后一次计算后发送停止标志 if {$i == [lindex $index_array end]} { send "0\r" } else { send "1\r" } } # 等待进程结束 expect eof
方式三:检查radex是否支持命令行参数
优先查看radex的帮助文档(./radex -h或./radex --help),如果它支持直接通过命令行传递参数(例如./radex -i 输入文件 -o 输出文件 -T 温度...),这是最可靠的方式,完全规避交互式输入的问题。
内容的提问来源于stack exchange,提问作者GhastM4n
相关产品推荐
相关产品推荐

