Заменить акцентированные символы с помощью perl-rename

Вопрос или проблема

Я стандартизирую название нескольких файлов одновременно, поэтому я написал регулярное выражение для perl-rename:

perl-rename 'y/A-Z/a-z/; s/ã|á|â/a/g; s/é|ê/e/g; s/í/i/g; s/õ|ó/o/g; s/ú/u/g; s/ç/c/g; s/(?<=\d-)*\s/_/g; s/_+/_/g; s/(?<=\d)_/-/' *

Это работает именно так, как и ожидалось:

2024-12-01 certidão de matrícula -> 2024-12-01-certidao_de_matricula

Тем не менее, я подумал, что это можно немного упростить, и придумал это:

perl-rename 'y/A-Z/a-z/; y/ãáâéêíõóúç/aaaeeioouc/; s/(?<=\d-)*\s/_/g; s/_+/_/g; s/(?<=\d)_/-/' *

Результаты, однако, не оправдали моих ожиданий. Например:

2024-12-01 certidão de matrícula -> 2024-12-01-certidaao_de_matraccula

Почему вторая команда не работает, если она должна выполнять прямую транслитерацию каждого ударного символа? Я даже не могу понять результат. Заранее спасибо.

Это происходит, потому что Perl не знает, что он должен обрабатывать имена файлов как UTF-8. Вместо этого он смотрит на отдельные байты, поэтому вы получаете частичные замены и дубликаты. Например, рассмотрим это:

% echo 'ä:ö:ä' | perl -pe 'y/ä/x/'
xx:x�:xx

Здесь ввод равен \xc3\xa4:\xc3\xb6:\xc3\xa4, и y/ä/x/ принимается как y/\xc3\xa4/x/ (с правой стороны x неявно дублируется). В результате UTF-8 ä превращается в xx, когда оба байта заменяются индивидуально, и UTF-8 ö ломается, когда заменяется только первый байт.

Команда s/// работает, потому что она ищет целую строку для замены, поэтому не имеет значения, интерпретируется ли она как один символ или два байта.

Вы можете исправить это, добавив use utf8 или -Mutf8, чтобы сказать Perl, что источник в UTF-8, и опцию -C, чтобы сообщить ему, что stdin/stdout в UTF-8.

% echo 'ä:ö:ä' | perl -Mutf8 -C -pe 'y/ä/x/'
x:ö:x

В скрипте переименования вы, вероятно, не сможете использовать -C, поэтому используйте переменную окружения PERL_UNICODE, например, с export PERL_UNICODE=AS (для аргументов и stdin/out), и включите use utf8 в вашу команду переименования и надеетесь, что это сработает.

Ответ или решение

Чтобы заменить акцентированные символы в названиях файлов с помощью утилиты perl-rename, вам необходимо правильно настроить кодировку, чтобы Perl корректно обрабатывал ваши данные как UTF-8. В вашем первом примере вы используете два разных подхода:

  1. Использование s/// для замены отдельных акцентированных символов.
  2. Использование y/// для трансляции символов.

Проблема в вашем втором подходе заключается в том, что Perl не интерпретирует файлы как UTF-8, а обрабатывает каждый байт отдельно, что приводит к некорректным заменам.

Причина некорректной работы

В вашем упрощённом варианте с использованием y/ãáâéêíõóúç/aaaeeioouc/ вы столкнулись с тем, что Perl видит не целые символы, а отдельные байты. В результате этого, когда UTF-8 символ мадрекций, такой как ä, заменяется, только его первый байт затрагивается, что приводит к неожиданным результатам.

Пример

Рассмотрим пример:

echo 'ä:ö:ä' | perl -pe 'y/ä/x/'

Результат будет

xx:x�:xx

Это связано с тем, что ä соответствует байтам \xc3\xa4, и Perl заменяет его на x, который занимает один байт, что приводит к возникновению ошибки при интерпретации выходного символа.

Решение проблемы

Настройка кодировки

Чтобы добиться корректной работы и избежать проблем с неверной интерпретацией символов, вы можете использовать следующие подходы.

  1. Использование модуля utf8: Добавьте в ваш код строку use utf8; для указания той кодировки, с которой будет работать Perl.

  2. Параметры окружения: Установите переменную окружения PERL_UNICODE, чтобы информировать Perl о том, что входные и выходные данные должны обрабатываться как UTF-8.

Пример корректного использования perl-rename:

export PERL_UNICODE=AS
perl-rename 'use utf8; y/A-Z/a-z/; y/ãáâéêíõóúç/aaaeeioouc/; s/(?<=\d-)*\s/_/g; s/_+/_/g; s/(?<=\d)_/-/' *

Заключение

Проблема, с которой вы столкнулись, связана с неверным обращением Perl к кодировке файлов. Чтобы избежать таких ошибок, всегда следите за настройками кодировки при работе с многоязычными данными. Используйте use utf8; и соответствующие параметры окружения для корректной работы с UTF-8. Следуя представленным рекомендациям, вы сможете успешно стандартизировать имена файлов и избежать неожиданных результатов в будущем.

Оцените материал
Добавить комментарий

Капча загружается...