如何使 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;
}
当我在 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;
}