android - 为什么 Android 的 "not the following character"正则表达式是 [!x] 而不是 [^x]?

标签 android regex bash adb regex-negation

我需要编写一个 bash 脚本,它将在 Android 设备上执行。除其他外,我需要这个脚本来计算字符串中特定字符的出现次数,因为 wc (字数统计)实用程序在 Android shell 中不可用,我这样做是这样的:

my_string="oneX two threeX"; x_amount="${my_string//[^X]}"; echo $x_amount; echo "${#x_amount}"

当我在桌面上运行上述命令时,它返回(正如我所期望的):

XX
2

但如果我在我的 Android 设备上执行相同的命令(通过 adb shell ),令我惊讶的是,结果是:

one two three
13

我发现(只是猜测)如果我将 ! 替换为 ^,那么该命令将变为:

my_string="oneX two threeX"; x_amount="${my_string//[!X]}"; echo $x_amount; echo "${#x_amount}";

然后,在 Android 上,它会产生我期望的结果:

XX
2

虽然同一命令在桌面上失败并显示以下消息:

event not found: X]

尽管我已经弄清楚如何“让它工作”,但我想了解以下几点:

  1. 除了 Android shell,还有什么地方使用了 [!X] 表示法,而不是 [^X]

  2. 这种表示法有什么特殊的名称吗?

  3. Android 不支持 [^X] 有什么具体原因吗?

P.S.:我需要在其上运行脚本的设备有相当旧的 Android 版本 (4.4),所以这个“问题”可能是特定于 Android 版本的,即使是这种情况,问题以上保留。

最佳答案

Android 的外壳是 mksh , witch 使用与 Bash 不同的 RegEx 或模式方言。

参见: File name patternsmksh's man-page :

    File name patterns
...
     [!...]  Like [...], except it matches any octet not inside the brackets.

让我们用字符串替换和负字符类模式 [!...] 语法测试一些 shell 兼容性:

#!/usr/bin/env bash

shells=( ash bash dash ksh93 mksh tcsh zsh )
compat=()
not_compat=()
for shell in "${shells[@]}"; do
  if [ "$(
    "$shell" <<'EOF' 2>/dev/null
my_string="oneX two threeX"
x_amount="${my_string//[!X]}"; echo "$x_amount${#x_amount}"
EOF
  )" = "XX2" ]; then
    compat+=("$shell")
  else
    not_compat+=("$shell")
  fi
done
echo "Shells that understands the [!...] negative class syntax:"
printf '%s\n' "${compat[@]}"
echo
echo "Shells that don't understand string substitution:"
printf '%s\n' "${not_compat[@]}"

输出:

Shells that understands the [!...] negative class syntax:
bash
ksh93
mksh
zsh

Shells that don't understand string substitution:
ash
dash
tcsh

另请注意 sed不理解 POSIX 否定字符组表示法 [!...],即使禁用其 Gnu 扩展也是如此:

sed --posix 's/[!X]//g' <<<'oneX two threeX'
one two three

但是

sed --posix 's/[^X]//g' <<<'oneX two threeX'
XX

关于android - 为什么 Android 的 "not the following character"正则表达式是 [!x] 而不是 [^x]?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57545437/

相关文章:

Android BLE 意外并反复重新连接到外围设备

android - Android 上 App 之间的切换会发生什么?

PHP - 将 Youtube URL 转换为嵌入 URL

linux - 在 concat() 中的 csv 中添加换行符

android - 无法识别使用 cordova-plugin-media 生成的 Ionic 2 音频文件

android - Facebook 评论 api phonegap

bash脚本-打印所有正在运行的jar的绝对路径

linux - 为什么 echo 从不打印

python - 通过正则表达式修复 .bib 文件标题

java - 解析包含多个符号的字符串会导致崩溃