sed:在分隔符

时间:2016-07-30 17:57:44

标签: batch-file sed

我正在使用旧游戏控制台的编译器,但此编译器只接受ANSI字符。这是一个问题,因为游戏是日语,需要UTF-8。作为一种解决方法,我编写了一个批处理脚本,它执行sed以用十六进制的等效字节值替换文档中的每个日文字符。

主要的sed脚本如下所示:

chcp 1252
sed "s|\[terminator\]|,$FF|g"^
;"s|ャ|,$00|g"^
;"s|ィ|,$01|g" ^
test.asm > test2.asm

所以像“ャィャ[终结者]”这样的字符串将被转换为“,$ 00,$ 01,$ 00,$ FF”。

问题是可以插入文本字符串的非日语字符,例如数字和标点符号,也会在代码中的其他地方使用,所以我不得不求助于这些字符的替代版本以防止sed例如,在每个注释之前转换分号,这会使编译过程失败。但是这种解决方法迫使用户将每个替换字符复制并粘贴到他们想要修改的字符串中,而不是像通常那样只键入它们。

所以,我的问题是,如何告诉sed只替换字符串分隔符(管道)之间的字符而不是在文档中的每个地方执行替换?

换句话说,我希望sed替换看起来像这样的东西:

<label> dw $1234 : db |ャィャ[terminator]|     ; Comment (blah ャィャ blah)

到此(管道和前导逗号将被删除):

<label> dw $1234 : db |,$00,$01,$00,$FF|     ; Comment (blah ャィャ blah)

请注意,评论部分保持不变。

2 个答案:

答案 0 :(得分:2)

sed中可能有办法做到这一点;但是维护起来很复杂且具有挑战性。我的建议是改用不同的语言,这很容易。这是Awk:

awk -F '|' '{ gsub(/\[terminator]/, "$FF", $2);
    gsub(/ャ/, ",$00", $2);
    gsub(/ィ/, ",$01", $2); } 1' test.asm >test2.asm

我在Unix上,单引号在这里最有意义。据我所知,CMD更喜欢双引号,这使事情复杂化;在最坏的情况下,可能将脚本放在一个文件中,并用awk -F "|" -f scriptfile.awk test.asm >test2.asm

调用它

如果您没有为您的平台安装Awk,那么在Perl,Python或Ruby中应该同样容易。 (Perl甚至带有a2p用于将Awk脚本转换为Perl。)

答案 1 :(得分:2)

    release-1.0 <--- release-1.1 <----------------------\
        |                                               |       
        v                                               |       
c1 <--- c2 <--- c3 <--- c4 <--- c5 <--- c6 <--- c7 <--- master

输出:

echo \
   '<address> dw $1234 : db |ャィャ[terminator]|     ; Comment (blah ャィャ blah)' | \
sed    's/\[terminator\]/,$FF/;
    :c1 s/ャ\(.*\)|/,$00\1|/;t c1;
    :c2 s/ィ\(.*\)|/,$01\1|/;t c2'

如果计算的LABEL名称如“ c1 c2 ”似乎很麻烦,那些 katakana 也可以作为唯一的LABEL:

<address> dw $1234 : db |,$00,$01,$00,$FF|     ; Comment (blah ャィャ blah)

注记。似乎 s earch g lobal 选项应该有效:

sed    's/\[terminator\]/,$FF/;
    :ャ s/ャ\(.*\)|/,$00\1|/;t ャ;
    :ィ s/ィ\(.*\)|/,$01\1|/;t ィ'

添加通配符 g lobal 无效,只会替换一个“a”用“ - ”:

echo abcdabcdabcd | sed 's/a/-/g'
-bcd-bcd-bcd

循环有效:

echo abcdabcdabcd | sed 's/a\(.*\)/-\1/g'
-bcdabcdabcd