【问题标题】:Ruby regular expressions for finding words用于查找单词的 Ruby 正则表达式
【发布时间】:2017-01-24 18:39:16
【问题描述】:

我对正则表达式很陌生。我正在使用正则表达式:

/\w+/

要检查单词,很明显这会有标点问题,但我不太清楚如何更改这个正则表达式。例如,当我从我创建的类中运行此命令时:

Wordify.new.regex(/\w+/).string("This sentence isn't 'the best-example, isn't it not?...").display

我得到了输出:

-----------
this: 1
sentence: 1
isn: 2
t: 2
the: 1
best: 1
example: 1
it: 1
not: 1
-----------

如何调整正则表达式使其匹配带撇号的单词,例如:isn't 作为一个单词,但在搜索 时只会匹配 the >'thethe'。像 stack-overflow 这样的单词中间的连字符应该分别匹配 return stackoverflow,这已经做到了。

此外,单词不能以数字开头或结尾,例如 test1241436test 应该变为 test,但 te7st 没问题。不应识别纯数字。

抱歉,我知道这是一个很大的问题,但我不确定从哪里开始使用正则表达式。如果可能的话,如果你能解释一下这个表达的意思,将不胜感激。

【问题讨论】:

  • 请记住,在 Ruby 和许多正则表达式库中,\w 包含下划线 _ 作为有效字符。
  • 请注意,通过排除"the'",您也排除了以"s" 结尾的所有格形式,如"I like Chris' hat"
  • 除了字符串的第一个或最后一个字符外,您所说的每个“内部”字符都可以是字母、数字或撇号。内部字母可以是别的吗?
  • 不,内部字符不能是其他任何东西,包括下划线等其他标点符号。

标签: ruby regex


【解决方案1】:
str = "This is 2a' 4test' of my agréable re4'gex, n'est-ce pas?"

r = /
    [[:alpha:]]            # match a letter
    (?:                    # begin the outer non-capture group
      (?:[[:alpha:]]|\d|') # match a letter, digit or apostrophe in a non-capture group
      *                    # execute the above non-capture group zero or more times
      [[:alpha:]]          # match a letter
    )?                     # close the outer non-capture group and make it optional
    /x                     # free-spacing regex definition mode

str.scan r
  #=> ["This", "is", "a", "test", "of", "my", "agréable", "re4'gex", "n'est", "ce", "pas"]

注意,如果要匹配的字符串是单个字符,则需要外部捕获组。

嗯。也许我们应该在内部非捕获组中添加一个连字符。

r = /[[:alpha:]](?:(?:[[:alpha:]]|\d|'|-)*[[:alpha:]])?/
str.scan r
  #=> ["This", "is", "a", "test", "of", "my", "agréable", "re4'gex", "n'est-ce", "pas"]

我现在很少使用匹配字符\w,主要是因为它匹配下划线,以及字母和数字。相反,我找到了POSIX bracket expression(搜索“POSIX”),它具有额外的(也许是主要的)好处,即它不是以英语为中心的。例如,匹配除下划线以外的单词字符为[[:alnum:]]

【讨论】:

    【解决方案2】:

    你可以做一些基本的事情:

    /[a-z]+(?:'[a-z]+)*/i
    

    将其扩展为允许使用 a2b 之类的词并避免使用 123abc abc123 和/或普通数字:

    /[a-z]+(?:'[a-z]+|\d+[a-z]+)*/i
    

    这两种模式没有使用特殊的正则表达式功能,只有基础。

    【讨论】:

    • "is3't"[/[a-z]+(?:'[a-z]+|\d+[a-z]+)*/i] #=> "is"。这是故意的吗?
    【解决方案3】:

    尝试使用[[:alpha:]] POSIX 字符类扫描字符串:

    s = "This a sentence isn't 'the best-example, isn't it not?... a1 2b 3c3 d4d 555 stack-overflow"
    s.scan(/[[:alpha:]](?:['\w]*[[:alpha:]])?/)
    # => ["This", "a", "sentence", "isn't", "the", "best", "example", "isn't", "it", "not", "a", "b", "c", "d4d", "stack", "overflow"]
    

    [第一次尝试]

    我将字符串拆分为由空格或连字符分隔的标记,然后根据您的规则清理每个标记,因为看起来它们可能会在您优化问题时进行调整:

    def tokenize(str)
      tokens = str.split(/(?:\s+|-)/)
      tokens.reduce([]) do |memo, token|
        token.gsub!(/(^\W+|\W+$)/, '')    # Strip enclosing non-words
        token.gsub!(/(^\d+|\d+$)/, '')    # Strip enclosing digits
        memo + (token=='' ? [] : [token]) # Ignore the empty string
      end
    end
    
    s = "This sentence isn't 'the best-example, isn't it not?... a1 2b 3c3 d4d 555 stack-overflow"
    puts tokenize(s).inspect
    #   ["This", "sentence", "isn't", "the", "best", "example", "isn't", "it", "not", "a", "b", "c", "d4d", "stack", "overflow"]
    

    显然,这个解决方案不仅仅使用正则表达式,但对我来说,它更容易理解和修改,然后(我想象的)一个大的正则表达式看起来像!

    【讨论】:

      猜你喜欢
      • 2014-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 2022-08-18
      • 2016-12-07
      相关资源
      最近更新 更多