如何使用Shell脚本正确替换配置文件中train_input_reader的input_path
如何用Shell脚本替换.config文件中指定的路径列表?
你遇到的问题主要有两个:一是ls输出的文件列表格式不符合配置文件需要的"file1", "file2"形式,二是sed命令的定位和替换逻辑没处理好,导致旧内容残留。下面一步步帮你解决:
第一步:生成符合格式的文件列表
首先,我们需要把train_new.record-*的文件列表转换成配置文件要求的带引号、逗号分隔的格式,而不是简单的空格分隔。推荐用find代替ls(避免文件名含空格等特殊字符的问题),配合sed和tr来处理:
# 生成格式为 "file1", "file2" 的字符串 formatted_files=$(find "${dataset_path}" -maxdepth 1 -name "train_new.record-*" | sort | sed -e 's/^/"/' -e 's/$/",/' | tr -d '\n' | sed 's/,$//')
解释每一部分:
find "${dataset_path}" -maxdepth 1 -name "train_new.record-*":在指定目录下查找目标文件,-maxdepth 1确保只找当前目录sort:按文件名排序(可选,保持列表有序)sed -e 's/^/"/' -e 's/$/",/':给每个文件名前后加上引号和结尾的逗号,比如train_new.record-001变成"train_new.record-001",tr -d '\n':把所有换行符去掉,变成一行sed 's/,$//':去掉最后一个多余的逗号
第二步:用sed正确替换配置文件内容
接下来,我们需要精准定位到train_input_reader块下的input_path行,替换整行内容,同时如果原来的路径是多行的话,清理掉残留的旧内容。
情况1:原始input_path是单行
如果你的.config里input_path是一行写的(像你最初展示的那样),用这个sed命令就足够:
# 替换train_input_reader下的input_path行,保留原缩进 sed -i.bak '/train_input_reader:/,/input_path:/{/input_path:/s/.*/ input_path: ['"${formatted_files}"']/}' "${folder}${config_path}"
解释:
/train_input_reader:/,/input_path:/:限定只在从train_input_reader:开始到input_path:结束的范围内操作/input_path:/s/.*/ input_path: ['"${formatted_files}"']/:找到input_path:行,把整行替换成带正确缩进和新路径列表的内容(注意是4个空格,和你原文件的缩进保持一致)-i.bak:修改文件的同时生成备份文件(后缀是.bak),如果是Linux系统可以用-i ''直接修改不备份,macOS需要带备份后缀
情况2:原始input_path是多行
如果你的input_path是分行写的(比如原来的内容跨了多行),用下面的命令可以清理掉所有旧的路径行:
sed -i.bak '/train_input_reader:/,/tf_record_input_reader/{ /input_path:/{ # 替换input_path行 s/.*/ input_path: ['"${formatted_files}"']/ # 循环读取后续行直到遇到],然后删除这些行 :loop n /]/!b loop d } }' "${folder}${config_path}"
这个命令会在train_input_reader块内找到input_path行,替换后继续读取后续行,直到遇到闭合的],然后删除这些旧的行,确保没有残留。
最终效果
执行完上面的命令后,你的.config文件里的train_input_reader部分就会变成:
train_input_reader: { tf_record_input_reader { input_path: ["train_new.record-001", "train_new.record-002"] } }
内容的提问来源于stack exchange,提问作者vRoganv
相关产品推荐
相关产品推荐

