You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动