为什么 bash 扩展全局变量替换在字节级别起作用?

为什么 bash 扩展全局变量替换在字节级别起作用?

我认为 bash 变量替换和通配符起作用特点分辨率,所以我很惊讶地看到它在字节等级。
我的一切locale都是 en_AU.UTF-8

当没有任何内容可以匹配并且模式允许零到多时,替换发生在字节水平,如随后的替换所示。我原以为它会移动到下一个特点,但它并不...

也许这只是一个奇怪的边缘案例模式,或者我错过了一些明显的东西,但我确实想知道这里发生了什么,除了这个特定模式之外,我可以在其他地方期待这种行为吗?

这是脚本(最初是尝试将字符串拆分为字符)。
我预计最后一次测试,对于 character ,最终只会得到一个单身的前面有空格,但字符的 3 个 UTF-8 字节前面各有一个空格。这会导致无效的 UTF-8 输出。

shopt -s extglob
for str in  $'\t' "ab"  ळ ;do
    printf -- '%s' "${str//*($'\x01')/ }" |xxd
done

输出:

0000000: 2009                                      .
0000000: 2061 2062                                 a b
0000000: 20e0 20a4 20b3                            . . .

答案1

您的问题的简短答案是 *(pattern-list) 将匹配给定模式的零次或多次出现。每个输入字节之间有零个 Unicode 字符 0001 实例。因此,替换操作将这零个实例中的每一个替换为一个空格。

也许你想这样做:

$ for str in  $'\t' "ab"  ळ ; do  
    printf -- '%s' "${str//+($'\x01')/ }" |xxd
  done)
0000000: 09                                       .
0000000: 6162                                     ab
0000000: e0a4 b3                                  ...

但更长的答案是,无论如何,路径名都不是文本。至少,就(类 Unix)操作系统而言,它们还不够。它们是字节序列。问题是这样的事情做起来很简单:

$ LC_ALL=latin1
$ mkdir 'áñ' && cd 'áñ'
$ LC_ALL=ga_IE.iso885915@euro
$ mkdir '€25' && cd '€25'
$ LC_ALL=zh_TW
$ pwd
# ... what should the output be?  And what about the output of:
$ /bin/pwd

每个语言环境都包含其他语言环境中不存在的字符。这个问题会影响诸如定位-r查找-正则表达式也;的论证定位-r是一个正则表达式,因此必须包含对字符类等内容的支持;但您不知道使用什么区域设置来确定路径名称中字符的字符类,或者即使有一个可用的区域设置可用于表示系统上的所有路径。

相关内容