【问题标题】:Regex for matching capitals匹配大写的正则表达式
【发布时间】:2011-03-25 22:56:44
【问题描述】:
 def normalized?

    matches = match(/[^A-Z]*/)
    return matches.size == 0

  end

这是我对字符串进行操作的函数,检查字符串是否只包含大写字母。它可以很好地排除不匹配,但是当我在像"ABC" 这样的字符串上调用它时,它说不匹配,因为显然matches.size 是 1 而不是零。里面好像有一个空元素。

谁能解释一下原因?

【问题讨论】:

  • 如果您的 Ruby 版本支持\p{Lu},您总是希望使用它或[\p{Lu}\p{Lt}][A-Z] 是在处理比打孔卡更现代的任何文本的代码中要刻意避免的那些代码气味反模式之一。
  • 好的,为什么这样更可取?它的速度是否优于 [A-Z]?
  • @Samuel - 为避免 unicode 十字军,指定您只关心识别行而不是包含字母 [A-Z] 如果这样做。
  • Samuel:如果正确性不重要,我可以让任何东西运行得无限快。所以呢?不是 [A-Z] 慢,而是这是错误的。 \p{Lu} 更好,尽管它仍然缺少 42 个大写代码点。
  • 我猜 \p{Lu} 也适用于 Ä 等字母?在我的情况下,虽然我严格只支持字母 A 到 Z,所以我想知道在我的情况下只使用 A-Z 不是更快吗?

标签: ruby regex match


【解决方案1】:

您的正则表达式错误 - 如果您希望它仅匹配大写字符串,请使用 /^[A-Z]+$/

【讨论】:

  • 好的,你能告诉我为什么是wong吗?
  • 当然 - 您在组 ([]) 中有一个克拉 (^),这意味着不是 A-Z,星号表示它根本无法匹配任何内容。所以我们在正则表达式的末尾抛出一个结束分隔符($)并将*更改为+以确保字符串至少有1个字符长。
  • @mway:我认为他很清楚他的正则表达式的作用。这就是为什么他试图检查匹配是否为空的原因。如果是,则字符串仅包含大写字母。这可能是一种过于复杂的方法,但如果 MatchData#size 做了他认为的那样,那将是完全正确的。
  • 是的,就像他说的那样,但感谢您提供替代的、更合乎逻辑的正则表达式 :)
  • +1 表示正确答案。 @Samuel - 这不是替代方案,它是唯一正确的答案。没有其他正则表达式仅与 A-Z 正则匹配。
【解决方案2】:

您的正则表达式不正确。 /[^A-Z]*/ 表示“匹配零个或多个不在AZ 之间的字符,位于字符串中的任何位置”。字符串ABC 有零个字符,不在AZ 之间,因此它匹配正则表达式。

将您的正则表达式更改为/^[^A-Z]+$/。这意味着“匹配一个或多个不在AZ 之间的字符,并确保字符串开头和结尾之间的每个字符都不在AZ 之间”。然后字符串ABC 将不匹配,然后您可以根据sepp2k 的答案检查matches[0].size 或其他内容。

【讨论】:

  • 如果他有一个不匹配的正则表达式,他肯定可以检查matches[0].size,因为matches可能是nil。他当前方法的重点是正则表达式将始终匹配,并且他正在检查它是否匹配空字符串或更实质性的内容。
【解决方案3】:

MatchData#size 返回正则表达式中捕获组的数量加一,以便md[i] 将访问有效组iff i < md.size。所以size返回的值只依赖于正则表达式,不依赖于匹配的字符串,永远不会为0。

你想要matches.to_s.sizematches[0].size

【讨论】:

  • 谢谢,你建议我保留正则表达式吗?
  • @Samuel:我会使用 mway 的正则表达式,因为说“字符串仅包含 A-Z 中的字符”比说“字符串不包含任何非 A-Z 的字符”更自然。
【解决方案4】:
ruby-1.9.2-p180>   def normalized? s
ruby-1.9.2-p180?>    s.match(/^[[:upper:]]+$/) ? true : false
ruby-1.9.2-p180?>  end
 => nil 
ruby-1.9.2-p180>  normalized? "asdf"
 => false 
ruby-1.9.2-p180>  normalized? "ASDF"
 => true 

【讨论】:

    【解决方案5】:

    正则表达式中的* 表示它匹配任意数量的非大写字符,包括零。所以它总是匹配一切。修复方法是删除*,然后它将无法匹配仅包含大写字符的字符串。 (尽管如果不允许使用零长度字符串,则需要进行不同的测试。)

    【讨论】:

      【解决方案6】:

      如果您想知道输入字符串完全由英文大写字母组成,即 A-Z,那么您必须删除 Kleene Star,因为它将匹配任何输入字符串中每个单个字符的前后(零长度匹配)。语句!s[/[^A-Z]/] 告诉您是否不匹配非 A 到 Z 字符:

      irb(main):001:0> def normalized? s
      irb(main):002:1>     return !s[/[^A-Z]/]
      irb(main):003:1> end
      => nil
      irb(main):004:0> normalized? "ABC"
      => true
      irb(main):005:0> normalized? "AbC"
      => false
      irb(main):006:0> normalized? ""
      => true
      irb(main):007:0> normalized? "abc"
      => false
      

      【讨论】:

      • 去掉 * 量词,同时仍然使用负 A-Z 类,当在匹配结果上放置 ! 条件时,仍然匹配空字符串。当空字符串并不真正表示由字母 A-Z 组成的字符串时,它会返回 true。请参阅我上面发布的真值表。
      • 类似!/[^A-Z]+/
      • 空字符串应该明确返回true,因为@Samuel 的要求是“检查字符串是否只包含大写字母”。空字符串只包含大写字母!s[/[^A-Z]/] 语句会告诉您是否不匹配非 A 到 Z 字符。这是一个正确的答案,因为 大写字母 表示 A 到 Z。
      • @Staffan The empty string contains only uppercase letters. 让我们测试一下这个理论"" =~ /[A-Z]/。不,空字符串只包含任何内容。
      • @sln 这是一个定义问题,我们似乎不同意。 :-) 我仍然声称 no characters string 是一种 uppercase only string。要说它不是仅大写的字符串,我们至少需要一个不是大写的字符——反证。 /[A-Z]/ 测试是否有至少一个大写字母,这与仅大写字母 不同。但是,这是一个子讨论。 :-)
      【解决方案7】:

      only 1 个正则表达式定义了一个只有 All 大写的字符串:

      def onlyupper(s)
      (s =~ /^[A-Z]+$/) != nil
      end

      真值表:

      /[^A-Z]*/:
       Testing  'asdf'     matched  'asdf'     length  4
       Testing  'HHH'      matched  ''         length  0
       Testing  ''         matched  ''         length  0
       Testing  '-=AAA'    matched  '-='       length  2
      --------
      /[^A-Z]+/:
       Testing  'asdf'     matched  'asdf'     length  4
       Testing  'HHH'      matched  nil
       Testing  ''         matched  nil
       Testing  '-=AAA'    matched  '-='       length  2
      --------
      /^[^A-Z]*$/:
       Testing  'asdf'     matched  'asdf'     length  4
       Testing  'HHH'      matched  nil
       Testing  ''         matched  ''         length  0
       Testing  '-=AAA'    matched  nil
      --------
      /^[^A-Z]+$/:
       Testing  'asdf'     matched  'asdf'     length  4
       Testing  'HHH'      matched  nil
       Testing  ''         matched  nil
       Testing  '-=AAA'    matched  nil
      --------
      /^[A-Z]*$/:
       Testing  'asdf'     matched  nil
       Testing  'HHH'      matched  'HHH'      length  3
       Testing  ''         matched  ''         length  0
       Testing  '-=AAA'    matched  nil
      --------
      /^[A-Z]+$/:
       Testing  'asdf'     matched  nil
       Testing  'HHH'      matched  'HHH'      length  3
       Testing  ''         matched  nil
       Testing  '-=AAA'    matched  nil
      --------
      

      【讨论】:

      • @tchrist 哦,是的,什么是 A-Z,我知道它不是 a-z?尽量停留在 A-Z 的主题上!
      • 你的函数错误地假装[A-Z] 以某种方式足以保证某些东西完全是大写的:它错过了ᴇ,ᴋ,Á,Æ,Þ,Ȝ,İ,Ə,Ⅻ等,这仍然只是拉丁文! A-Z 显然是错误的:它错过了 968 个大写代码点。 必须使用\p{Uppercase} 来保证这一点。请注意,派生的二进制属性 \p{Uppercase} 不同于一般类别 \p{Uppercase_Letter} aka \p{Lu}。那是因为存在算作大写的非字母,比如像Ⅷ这样的罗马数字和像Ⓐ这样的带圆圈的字母都是\p{Uppercase}\P{Lu}
      • 查询者请求有关如何匹配大写的信息。正确回答问题。
      • 我猜他没有,因为他只关心匹配 A-Z。问题回答正确。
      • 直到你重命名你的函数,当它说 onlyupper 时它是在撒谎。我已经解释了仅上部的实际含义。你写的完全不正确。
      【解决方案8】:

      这个问题需要一个更明确的答案。正如tchrist 评论的那样,我希望他能回答。 “匹配大写的正则表达式”要使用:

      /\p{Uppercase}/
      

      正如 tchrist 提到的“不同于一般类别 \p{Uppercase_Letter} aka \p{Lu}。那是因为存在算作大写的非字母”

      【讨论】:

      • 那么你会如何回答这个人的问题呢? \p{Uppercase} 将匹配单个大写 Unicode 频谱字母。他想确保字符串都是大写的字母。我想一个简单的解决方法是匹配单个 \P{Uppercase} 然后失败。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-07
      • 1970-01-01
      • 1970-01-01
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多