如何使 uc() 在 Perl 中工作,就像 toupper() 在区域设置感知 POSIX 环境中在 AWK 中所做的那样?

How to make uc() work in Perl like toupper() does in AWK in a locale-aware POSIX environment?

当我在 AWK 中使用 toupper() 等函数时,它们会自动识别区域设置并在用户当前的区域设置中处理文本。

我想在 Perl 脚本中做同样的事情,但到目前为止都失败了。

为此,我编写了以下用于测试 Perl 和 AWK 的 ASCII shell 脚本:

$ unexpand -t 2 << 'END_SCRIPT' | tee case3 && chmod +x case3
#! /bin/sh
{
  iconv -cf UTF-7 \
  | case  in
  awk)
    awk '{
      print "original", [=11=]
      print "to lower", tolower([=11=])
      print "to upper", toupper([=11=])
    }'
    ;;
  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"-case 脚本中做错了什么。

注意:我希望我的脚本需要 UTF-8 语言环境,它应该适用于任何可以代表我 [=40= 中使用的德语变音符号的语言环境] 文件。

如果您感到好奇,以上结果是使用以下区域设置生成的:

$ 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=

这与您的要求不完全相同,因为它根据 Unicode 规则而不是语言环境规则确定大小写,但它适用于所有语言环境(UTF-8 和其他语言):

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