【问题标题】:What's the difference between [[:upper:]] and [:upper:] (bash)?[[:upper:]] 和 [:upper:] (bash) 有什么区别?
【发布时间】:2019-07-29 07:36:10
【问题描述】:

所以我在 macOS High Sierra 10.13.6 下使用 bash 3.2.57(1)-release,我正在尝试编写一个需要不区分大小写输入的 bash 脚本。我读到使用tr "[:upper:]" "[:lower:]" <<< "$(echo AaBbCcDd)" 会将整个字符串转换为小写,它确实如此。但是,我曾在其他地方阅读过使用'[[:UPPER:]]' 和'[[:LOWER:]]' 来代替。这些似乎仍然有效,但它让我想知道,这两者之间有什么区别吗?

【问题讨论】:

  • 我认为你的意思是显示 [[:upper:]] 和 [[:lower:]] 因为,你拥有的那些是无效的
  • 我对此进行了测试,您似乎是对的。我不记得在哪里,但我很确定我也看到了那个表格。我会保持原样,但是如果您觉得无论如何都应该更改它,请随意这样做:-)
  • 附带说明:<<< "$(echo AaBbCcDd)" 非常复杂。只是<<< AaBbCcDd 的效果是一样的。

标签: regex bash shell tr


【解决方案1】:

在正则表达式中,[[:upper:]] 表示“任何大写字母”。但这是更通用机制的一个实例。外括号[…] 和内括号冒号[:…:] 具有不同的含义。外括号围绕着一个字符集。在字符集中,您可以使用单个字符、2-9 等范围以及使用括号冒号语法的字符类。例如,正则表达式 [2-9_[:upper:]] 匹配 2 到 9 之间的任何大写字母或下划线或数字。

tr 替换单个字符,而不是正则表达式。 (还有另一个替换正则表达式的工具:sed。)它的参数是一个字符集,即你要放在括号内的内容。

tr '2-9_[:upper:]' 'X'

等价于

sed 's/[2-9_[:upper:]]/X/g'

你可以写tr '[[:upper:]]' '[[:lower:]]'这样的东西,它和tr '[:upper:]' '[:lower:]'的效果一样。但这并不是因为外部括号有任何特殊含义。这是因为您将[ 替换为[,将大写字母替换为相应的小写字母,并将] 替换为]。自己替换括号是没有效果的。

(顺便说一下,bash 4 有一个内置的大小写转换机制:all_uppercase=${var^^}; all_lowercase=${var,,}。但这在 bash 3 中不存在,这是 Apple 在 macOS 上提供的。要获得 bash 4,您需要Brew 等第三方发行版。)

【讨论】:

  • 感谢您的详细解答!我最初看到了^^ 和,,,并希望我可以使用它。我确实有 brew,但我喜欢在 bash 方面保持库存。
  • 您好,在与sed 搞混时,我偶然发现了类似这样的其他东西。例如,echo '1A2B3C' | sed 's/[[:upper:]]/_/g' 生成 1_2_3_,但执行 echo '1A2B3C' | sed 's/[:upper:]/_/g' 会打印 1A2B3C。这有什么不同的原因吗?
  • @leetbacoon 在第二个中,第一个也是唯一的[ 开始一个字符集,直到]。它相当于s/[:epru]/_/g。在/[[:upper:]]/_/g 中,第一个[ 开始一个字符集,而在该字符集中[:upper:](从正则表达式中的第二个[ 开始)具有“任何大写字母”的特殊含义。
猜你喜欢
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 2022-01-13
  • 2012-02-25
相关资源
最近更新 更多