Bash脚本修改结构化文本:提取引号内容并替换失败求助
解决Bash脚本提取翻译文本无输出的问题
问题背景
我需要编写Bash脚本处理Banished游戏的结构化StringTable资源文件,文件格式如下:
StringTable resource { Entry _strings [ //CUSTOM UI { String _name = "CCIconChartTip"; String _text = "Icon Chart for Colonial Charter."; } { String _name = "CCIconChart"; String _text = "Icon Chart"; } . . . ] }
需求是仅提取引号内的_text内容供翻译替换,但我编写的脚本无法正常运行,没有任何内容输出。
我的脚本代码:
while true do ((string_num++)) ori_string=$(sed -n '/string_num/p' $path) mid=${ori_string%\"} #To cut a line started with " From behind ori=${mid##\"} #To cut a line ended with " echo "Original : $ori" echo "Translate : " read -r trans if [ "$trans" -eq "p" ] # To skip then continue elif [ "$trans" -eq "q" ] # To quit then break fi sed 'string_nums/ori/trans/g' path done
执行脚本后的输入输出:
$ sh Banished_translator.sh Enter a file name NewLimitStringTable.rsc Skip to b. Quit to q Original : Translate :
问题分析与修复方案
你的脚本存在几个关键逻辑错误,导致无输出和功能异常,我逐一拆解并给出修复方案:
1. 缺失文件路径读取逻辑,sed语法错误
- 脚本开头需要输入文件名,但原脚本没有读取用户输入的逻辑,
$path变量为空,导致sed无法找到目标文件。 - sed的
/string_num/p是匹配包含string_num字符串的行,而非第N行,正确读取第N行的语法是sed -n "${string_num}p" "$path"。
2. 字符串截取逻辑不匹配目标格式
原脚本的截取方式仅适用于整行只有一个引号包裹内容的场景,但目标文件一行包含多个引号(比如同时有_name和_text的引号内容),需要精准提取_text后的引号内容。
3. 条件判断语法错误
-eq是数值比较运算符,字符串比较应该用=或==。- 注释说明跳过用
p,但执行提示写的是Skip to b,需要统一输入标识。
4. sed替换逻辑错误
sed替换命令格式错误,且未指定目标文件,也没有原地修改的参数(需要-i),同时应该定位到目标行的_text值,而非全局替换。
修复后的完整脚本
#!/bin/bash # 读取目标文件路径 echo "Enter a file name:" read -r path # 检查文件是否存在,避免无效操作 if [ ! -f "$path" ]; then echo "Error: File $path does not exist!" exit 1 fi # 提取所有包含_text的行,逐行处理(带行号) grep -n '_text = "' "$path" | while read -r line; do # 拆分行号和行内容 line_num=$(echo "$line" | cut -d: -f1) content=$(echo "$line" | cut -d: -f2-) # 精准提取_text后的引号内文本(用正则正向预查) ori=$(echo "$content" | grep -oP '(?<=_text = ")[^"]+') echo -e "\nOriginal : $ori" echo "Translate (enter 'p' to skip, 'q' to quit):" read -r trans # 处理用户输入 if [ "$trans" = "q" ]; then echo "Quitting..." exit 0 elif [ "$trans" = "p" ]; then echo "Skipping this entry..." continue fi # 原地替换目标行的原始文本为翻译内容 sed -i "${line_num}s/\"$ori\"/\"$trans\"/" "$path" echo "Replaced successfully!" done echo "All entries processed!"
脚本说明
- 先检查文件是否存在,避免无效操作。
- 用
grep -n '_text = "'精准定位所有包含翻译文本的行,同时获取行号。 - 借助
grep -oP的正则正向预查提取引号内的文本,比字符串截取更可靠。 - 用户输入处理使用字符串比较
=,支持跳过(p)和退出(q)。 - 用
sed -i原地修改目标行内容,确保只替换_text对应的引号内容,不影响其他字段。
测试效果
执行脚本后,会逐行显示_text的原始内容,输入翻译内容后自动替换到文件中;输入p可跳过当前项,输入q直接退出脚本。
内容的提问来源于stack exchange,提问作者김건우 Kim Geonwoo




