Как заставить uc () работать в Perl так же, как toupper () в AWK в среде POSIX с поддержкой локали? - PullRequest
0 голосов
/ 11 февраля 2019

Когда я использую функции типа toupper () в AWK, они автоматически учитывают локали и обрабатывают текст в текущей локали пользователя.

Я хотел бы сделать то же самое в скрипте Perl, но не получилосьпока что.

Для этого я написал следующий сценарий оболочки ASCII для тестирования Perl и AWK:

$ unexpand -t 2 << 'END_SCRIPT' | tee case3 && chmod +x case3
#! /bin/sh
{
  iconv -cf UTF-7 \
  | case $1 in
  awk)
    awk '{
      print "original", $0
      print "to lower", tolower($0)
      print "to upper", toupper($0)
    }'
    ;;
  perl)
    perl -e '
      use locale;
      while (defined($_= <>)) {
        print "original ", $_;
        print "to lower ", lc;
        print "to upper ", uc;
      }
    '
  esac \
  | iconv -ct UTF-7 | iconv -cf UTF-7
} << 'EOF'
+AMQ-gypten
S+APw-d
+APY-stlich
EOF
END_SCRIPT

Обратите внимание на вещи iconv UTF-7 в конце скрипта: Этопросто пропустить любые символы из вывода, который не может представлять текущая локаль.

Вот вывод, когда я запускаю скрипт для тестирования AWK:

$ ./case3 awk
original Ägypten
to lower ägypten
to upper ÄGYPTEN
original Süd
to lower süd
to upper SÜD
original östlich
to lower östlich
to upper ÖSTLICH

Это выглядит довольно хорошо, и какэто должно быть.

Теперь то же самое для Perl:

$ ./case3 perl
original Ägypten
to lower gypten
to upper ÄGYPTEN
original Süd
to lower sd
to upper SüD
original östlich
to lower stlich
to upper öSTLICH

Очевидно, что это приводит к другому выводу и работает просто не правильно.

Я был бы признателен, чтобы знать, что янеправильно в "perl" -сценарии скрипта.

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

Если вам интересно, вышеуказанные результаты были получены при следующих настройках языка:

$ locale
LANG=de_AT.UTF-8
LANGUAGE=de_AT.UTF-8:de.UTF-8:en_US.UTF-8:de_AT:de:en_US:en
LC_CTYPE="de_AT.UTF-8"
LC_NUMERIC="de_AT.UTF-8"
LC_TIME="de_AT.UTF-8"
LC_COLLATE="de_AT.UTF-8"
LC_MONETARY="de_AT.UTF-8"
LC_MESSAGES="de_AT.UTF-8"
LC_PAPER="de_AT.UTF-8"
LC_NAME="de_AT.UTF-8"
LC_ADDRESS="de_AT.UTF-8"
LC_TELEPHONE="de_AT.UTF-8"
LC_MEASUREMENT="de_AT.UTF-8"
LC_IDENTIFICATION="de_AT.UTF-8"
LC_ALL=

1 Ответ

0 голосов
/ 11 февраля 2019

Это не совсем то, что вы просили, поскольку он определяет регистр на основе правил Unicode вместо правил локали, но он будет работать для всех локалей (UTF-8 и других):

use open ':std', ':locale';
while (<>) {
    print "original ", $_;
    print "to lower ", lc;
    print "to upper ", uc;
}
...