不可读的字符串与仅包含可读字符的正则表达式匹配

不可读的字符串与仅包含可读字符的正则表达式匹配

考虑以下命令:

STR="Êîðîëü è Øóò"; # Invalid (Russian in unrecognized encoding)
#STR="а б в г д"; # Valid (Russian)
#STR="a b c d e"; # Valid (English)
#STR="a b c d e а б в г д"; # Valid (English and Russian)



# The regex consists of latin and Russian characters
REGEX="^[a-zA-Zа-яА-Я ]+$"

if ! [[ "$STR" =~ $REGEX ]] ; then
  echo "Unreadable string: ""$STR";
fi


$ echo $LC_ALL
ru_RU.UTF-8

我期望"Unreadable string: Êîðîëü è Øóò"有输出,但什么也没有。

答案1

除了 POSIX 语言环境之外,POSIX 未指定likeA-Z或match 的范围(对于,不明显)。а-яA-Zа-я

只有在 POSIX 语言环境中,您才能获得仅[A-Z]匹配字符的保证。ABCDEFGHIJKLMNOPQRSTUVWXYZ

在其他区域设置中,行为因实现而异。有些可以匹配在之前A和之后排序的任何整理元素(可以是字符或字符序列)Z(可能包括ch,xÁ,但不Ź包括在内),或者它们可以匹配代码点大于A且小于的字符语言环境的字符集中的字符集Z,或者他们可以以不同的方式使用语言环境的排序规则数据...另请注意,并非每个人都同意任何给定脚本的字母顺序(例如在这种情况下为拉丁语或西里尔语),因此您对于在其字符集中包含这些脚本的不同区域设置(即使是相同的字符集),将会获得不同的行为。

如果您想匹配任何脚本中的任何字母字符,请使用[[:alpha:]],如果您想根据 UTF-8 中的代码点匹配字符范围,您可以尝试使用C.UTF-8许多系统上可用的区域设置。

如果您想匹配拉丁文中的任何字母,您可以使用perlor pcre's \p{Latin}(包括é, Ê...)。在zsh

set -o rematchpcre
[[ $x =~ '^(\p{Latin}|\p{Cyrillic})$' ]]

您可以将拉丁字母限制为仅在 ASCII 中找到的字母( still withzsh和 still with rematchpcre):

[[ $x =~ '^((?=[[:ascii:]])\p{Latin}|\p{Cyrillic})$' ]]

尽管在 , 中有效rematchpcre,但^([a-zA-Z]|\p{Cyrillic})$具有相同的效果,因为 PCRE 和 in 中的范围zsh基于代码点值,并且这些字母保证具有相同的代码点,并且位于英语字母顺序中,所有语言环境均基于 ASCII 和基于 EBCDIC 的 POSIX至少系统。

或者,如果您只想要一个子集,则可以明确列出字符,以避免所有歧义:

[[ $x =~ ^[ABC...XYZabc...xyzабв...эюя]$ ]]

您始终可以将它们存储在变量中,例如:

ascii_upper=ABC...XYZ
ascii_lower=abc...xzy
cyr_upper=...
[[ $x =~ ^[$ascii_upper$ascii_lower$cyr_upper...]$ ]]

相关内容