我在 Linux 上使用 bash。我从以下 if 语句中获得了成功,但这不应该返回失败代码吗?
if [[ ? = [???] ]] ; then echo yes ; fi
Run Code Online (Sandbox Code Playgroud)
正方形不等于任何字符,所以我不明白为什么我会得到成功代码。
在我的案例中保留双括号对我来说很重要。
在这种情况下有没有其他方法可以做一个范围,或者有什么其他建议?
Sté*_*las 29
这是这些字符具有相同排序顺序的结果。
你还会注意到
sort -u << EOF
?
?
?
?
EOF
Run Code Online (Sandbox Code Playgroud)
只返回一行。
或者那个:
expr ? = ?
Run Code Online (Sandbox Code Playgroud)
返回 true(根据 POSIX 的要求)。
GNU 系统附带的大多数语言环境都具有许多具有相同排序顺序的字符(甚至是字符序列(整理序列))。在那些的情况下????这是因为没有定义顺序,而那些没有定义顺序的字符在 GNU 系统中最终具有相同的排序顺序。有些字符被明确定义为具有相同的排序顺序,例如 ? 和 ?(尽管(尽管对我来说)没有明显的(对我来说)如何完成的真正逻辑或一致性)。
这是令人惊讶和虚假行为的根源。我最近在 Austin 组(POSIX 和单一 UNIX 规范背后的主体)邮件列表上提出了这个问题,并且讨论仍在进行中,截至 2015 年 4 月 3 日。
在这种情况下,我不清楚是否[y]
应该匹配x
wherex
和y
sort 相同,但由于括号表达式旨在匹配整理元素,这表明该bash
行为是预期的。
无论如何,我想[?-?]
或至少[?-?]
应该匹配?
.
您会注意到不同的工具表现不同。ksh93 的行为类似于bash
GNUgrep
或sed
不。其他一些 shell 有不同的行为,有些yash
甚至更多。
要获得一致的行为,您需要一个所有字符排序不同的语言环境。C语言环境是典型的语言环境。但是,大多数系统上 C 语言环境中的字符集是 ASCII。在 GNU 系统上,您通常可以访问C.UTF-8
可用于处理 UTF-8 字符的语言环境。
所以:
(export LC_ALL=C.UTF-8; [[ ? = [???] ]])
Run Code Online (Sandbox Code Playgroud)
或标准等价物:
(export LC_ALL=C.UTF-8
case ? in ([???]) true;; (*) false; esac)
Run Code Online (Sandbox Code Playgroud)
应该返回false。
另一种选择是仅设置LC_COLLATE
为 C,它可以在 GNU 系统上工作,但不一定适用于其他可能无法指定多字节字符排序顺序的系统。
其中的一个教训是,在比较字符串时,相等并不像人们所期望的那样清晰。平等可能意味着,从最严格到最不严格。
现在,对于 2 或 3,假设两个字符串都包含有效字符。在 UTF-8 和其他一些编码中,某些字节序列不能形成有效字符。
因此,1 和 2 不一定等效,或者因为某些字符可能具有不止一种可能的编码。这通常是像 ISO-2022-JP 这样的有状态编码的情况,其中A
可以表示为41
或1b 28 42 41
(1b 28 42
作为切换到 ASCII 的序列,您可以根据需要插入任意数量的那些,这不会有什么区别),尽管我不会期望这些类型的编码仍在使用中,并且 GNU 工具至少通常无法正常使用它们。
还要注意,大多数非 GNU 实用程序无法处理 0 字节值(ASCII 中的 NUL 字符)。
使用哪些定义取决于实用程序和实用程序实现或版本。POSIX 对此并不是 100% 清楚。在 C 语言环境中,所有 3 个都是等效的。在那个 YMMV 之外。