perl -pi -e "s/\x22message\x22\s+\x22Боже, ты посмотри вокруг, что происходит!\x22/\x22message\x22 \x22\x22/g;" "D:\Sav\scripts\chat_wheel.txt"
В этой команде нет ничего плохого, кроме русской текстовой части, которую я хочу удалить.
Боже, ты посмотри вокруг, что происходит!
Когда я запускаю его в cmd.exe, я получаю следующее сообщение об ошибке.
Вложенные квантификаторы в регулярном выражении; отмечен <-- ЗДЕСЬ в m/\x22message\x22\s+\x22??? <-- ЗДЕСЬ?,?????????????????,?????????????!\x22/ at -e строка 1.
Итак, как мне заменить русскую фразу, сохранив команду в виде одной строки? это вообще возможно?
Моя консоль использует CP 65001 (UTF-8). [От Win32::GetConsoleCP()]
Моя активная кодовая страница (ACP) — 1252 [От Win32::GetACP()].
Мой файл закодирован с использованием UTF-8.
Решение проблемы
Бзаменяется на ?. Это связано с тем, что она не поддерживается кодовой страницей консоли, активной кодовой страницей или и тем, и другим.
Кодовая страница вашей консоли установлена на 65001 или UTF-8. Таким образом, ваша консоль может обрабатывать любые символы из набора символов Unicode. Проблема явно не здесь.
Каждый системный вызов Windows, работающий со строками, бывает двух видов. Разновидность "Wide", использующая UTF-16le, и разновидность "A"NSI, использующая активную кодовую страницу. Если бы Perl использовал интерфейс «W» для получения параметров командной строки, у нас не было бы этой проблемы. Вместо этого Perl использует интерфейс «A» для этого (и всех других) системных вызовов.
Это означает, что Perl может принимать только аргументы командной строки, которые могут быть представлены активной кодовой страницей. В вашем случае это 1252, а набор символов cp1252 не включает символы кириллицы.
Предполагая, что мы не хотим заменять каждый символ escape-символом (например, как вы заменили двойные кавычки на "), нам нужно будет сделать что-то другое.
Поскольку мы не можем передать скрипт с помощью аргумента, нам нужно предоставить его с помощью файла, а не с помощью -e. Или через трубу.
echo s/"message"\s+"\KБоже(?=")// | perl -i -p - file.txt
Лучшим, но более радикальным решением было бы изменить ACP Perl на 65001.
Есть вторая проблема.
Perl ожидает, что его исходный код будет закодирован с использованием (8-битного чистого) ASCII, если вы не предоставите use utf8;. Так что пока вы думаете, что проходите s/...Боже...//, на самом деле вы проходите s/...\xD0\x91\xD0\xBE\xD0\xB6\xD0\xB5...//.
Это работает нормально, отчасти потому, что вы также не декодируете свой входной файл. Но это может привести к неожиданностям. Например, "Б" =~ /^[Бж]\z/( "\xD0\x91" =~ /^[\xD0\x91\xD0\xB6]\z/) вернет false!
Чтобы исправить это в сценарии, вы должны использовать
use utf8; # Source code is using UTF-8.
use open ':std', ':encoding(UTF-8)'; # Terminal provides & expects UTF-8.
-Cсделаю здесь.
echo s/"message"\s+"\KБоже(?=")// | perl -i -C -p - file.txt
Комментариев нет:
Отправить комментарий