计算单词中的大写字符

Count uppercase characters in a word

我需要计算一个单词中有多少个大写字母。我该怎么做?

我会使用 grep -o '[A-Z]' 来匹配大写,然后计算出现了多少次:

$ grep -o '[A-Z]' <<< "heLLo" | wc -l
2

或者更好(,总是提供好的信息!),使用 [[:upper:]] 这样大写字母也会考虑在您的语言环境中定义的那些:

$ grep -o '[[:upper:]]' <<< "heLLo" | wc -l
2

我喜欢这个:

echo "$word" | tr -dc A-Z | wc -c

简单地删除所有非大写的字符并计算剩下的字符。

您可能更喜欢 tr -dc [:upper:],但我发现 A-Z 更易于使用。

tl;dr

对于区域设置感知的解决方案,因此也适用于重音个字符,使用:

  • 任一个:[[:upper:]] 变体。

  • 或:的以下变体

echo "heLLÖ, world" | tr -dC '[:upper:]' | wc -m  # -> 3

需要进行更改才能正确处理非 ASCII、多字节编码的字符。
请继续阅读以获取详细说明。


使上述命令可识别区域设置的关键:

  • tr-C 选项使用基于 字符 的补码,而不是 -c,后者使用基于 byte 的补码;虽然 -c-C 在某些 tr 实现中可能表现相同,但 POSIX defines only -C as the locale-aware variant.

  • [:upper:] 确保使用 活动语言环境的 定义大写字符,而 A-Z 仅包含 unaccented(仅 ASCII)从 "A" 到 "Z" 的字母。

  • wc-m 选项计数 个字符 (可能包含 多个 现在流行的 UTF-8 编码中的字节);相比之下,-c 计数 字节 ,在上面的示例中,它会报告 4 而不是预期的 3,因为 Ö 被编码为 2 字节。


现在让我们看一下威廉的回答中的一句话:

You might prefer tr -dc [:upper:], but I find A-Z easier to use.

  • 这错误地暗示 [:upper:]A-Z 可以互换使用,选择一个而不是另一个只是偏好或方便的问题 - 然而,如上所述,[:upper:] 是语言环境感知的,而 A-Z 不是。
  • 此外,使用 [:upper:] unquoted 使其受到路径名扩展(通配)的影响,这意味着如果当前目录恰好包含名为 :uper[:upper:] 将扩展到它们的名称,这显然是不希望的。原因是 [:upper:] 被 shell 视为 字符 class.
  • wc -c,计算 字节 ,恰好与 A-Z 一起工作,因为根据定义,所有匹配的字母都是 单个-byte 个字符;但是为了区域设置切换到 [:upper:] 需要切换到 wc -m,以便正确计数(可能是多字节) 个字符 .