sed を使用して文字列の一部を無視します。

sed を使用して文字列の一部を無視します。

したがって、私のファイルのテキスト形式は次のようになります。

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 -Mutf8Unicode設定(この素晴らしい答えに感謝します。Unicode文字のtrシミュレーション?)
  • -F: -lane:フィールド区切り文字として使用され、配列@Fに保存されます(参照:https://perldoc.perl.org/perlrun.html#Commandスイッチ他のオプションの場合)
  • $F[-1]@F配列の最後のフィールド
  • \{[^{}]+\}(*SKIP)(*F)|[a-z]+[a-z]+ここでは、部品は一致する必要がありますが、\{[^{}]+\}そのまま維持する必要があると言います。
  • $&=~tr|abc|абц|r一致する部分を音域
  • gegすべての一致を置き換えるための修飾子、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■式は一重引用符ではなく二重引用符で囲まれているため、記号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} бац",

関連情報