所以,我的文件的文本格式如下:
untranslatedString : "translated string",
我需要将“翻译字符串”部分中的字符替换为其西里尔字母表示形式。我用这样的东西:
paste <(sed 's/\([^:]\+:\)\([^:]\+\)/\1/' resources.js) <(sed 's/[^:]\+:\([^:]\+\)/\1/;y/abc/абц/' resources.js)
(abc/абц/ 部分实际上更长并且包括所有字符,这是为了说明目的)。
问题出现在这样的行中:
abcTestString : "abc {ccb} bbc",
{} 之间的所有内容都应保留其原始状态,即。字符不应该被替换。结果应该是:
abcTestString : "aбц {ccb} ббц",
并不是
abcTestString : "aбц {ццб} ббц",
此外,每行可以有多个 {} 部分。
我怎样才能做到这一点?
答案1
如果你可以使用perl
$ s='abcTestString : "abc {ccb} bbc",'
$ echo "$s" | perl -Mopen=locale -Mutf8 -F: -lane '
$F[-1]=~s/\{[^{}]+\}(*SKIP)(*F)|[a-z]+/$&=~tr|abc|абц|r/ge;
print join ":",@F'
abcTestString : "абц {ccb} ббц",
-Mopen=locale -Mutf8
unicode 设置(感谢这个精彩的答案unicode 字符的 tr 模拟?)-F: -lane
用作:
字段分隔符,保存在@F
数组中(参见https://perldoc.perl.org/perlrun.html#命令开关对于其他选项)$F[-1]
@F
数组的最后一个字段\{[^{}]+\}(*SKIP)(*F)|[a-z]+
在这里我们说该[a-z]+
部分必须匹配,但\{[^{}]+\}
应保持原样$&=~tr|abc|абц|r
对匹配部分进行音译ge
g
用于替换所有匹配项的修饰符,用于e
允许替换部分中的 Perl 代码的修饰符
如果代码太大而无法从命令行处理,请将其更改为程序
$ echo "$s" | perl -MO=Deparse -Mopen=locale -Mutf8 -F: -lane '
$F[-1]=~s/\{[^{}]+\}(*SKIP)(*F)|[a-z]+/$&=~tr|abc|абц|r/ge;
print join ":",@F'
BEGIN { $/ = "\n"; $\ = "\n"; }
use open (split(/,/, 'locale', 0));
use utf8;
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
our @F = split(/:/, $_, 0);
$F[-1] =~ s[\{[^{}]+\}(*SKIP)(*F)|[a-z]+][use utf8 ();
$& =~ tr/abc/\x{430}\x{431}\x{446}/r;]eg;
print join(':', @F);
}
答案2
如果您想留在sed
:
sed 's/"/"_/;:l
s/_[^{]*/&_/;h
s/.*_\(.*\)_.*/\1/
y/abc/абц/;G
s/\(.*\)\n\(.*\)_.*_\([^}]*}\)\{0,1\}/\2\1\3_/
/_$/!bl
s/_//'
处理过程中使用下划线作为标记。如果下划线可以是文件的一部分,请使用不同的分隔符。
这个想法是标记字符串的一部分,保存一个副本以保留空间,删除标记之外的所有内容,进行转换,取回副本,用转换后的部分组成一个字符串并将下划线向前移动。如果 中有一部分{}
,则跳过该部分。
如果您有兴趣,我可以提供更详细的解释。
答案3
sed -rf <(echo ':l'; printf 's/("| [^{]*)%s/\\1%s/g\n' a а b б c ц; echo 'tl') input.txt
或者更简洁,但也更容易出错,因为sed
s 表达式用双引号括起来,而不是用单引号括起来,因此bash
应该转义特殊字符,例如$
符号。
sed -r ":l; $(printf 's/("| [^{]*)%s/\\1%s/g;' a а b б c ц) tl" input.txt
解释(第一个命令被执行)
sed -f script-file
- 将脚本文件的内容添加到要执行的命令中。
<()
- 流程替代。它允许将命令输出表示为文件并将其传递给需要文件的命令。
echo ':l'; printf 's/("| [^{]*)%s/\\1%s/g\n' a а b б c ц; echo 'tl'
- 它正在转换为下一个sed
命令序列:
:l
s/("| [^{]*)a/\1а/g
s/("| [^{]*)b/\1б/g
s/("| [^{]*)c/\1ц/g
tl
测试:
输入
abcTestString : "abc {bcb} bbc",
abcTestString : "bbc {acb} bbc {bcb}",
abcTestString : "acc {cab} {ccb} bbc",
abcTestString : "cbc {ccb} bac {aca} bac",
输出
abcTestString : "абц {bcb} ббц",
abcTestString : "ббц {acb} ббц {bcb}",
abcTestString : "ацц {cab} {ccb} ббц",
abcTestString : "цбц {ccb} бац {aca} бац",