Ruby регулярное выражение, извлекающее слова - PullRequest
11 голосов
/ 17 ноября 2011

В настоящее время я изо всех сил пытаюсь придумать регулярное выражение, которое может разбить строку на слова, где слова определяются как последовательность символов, окруженная пробелами или заключенная в двойные кавычки.Я использую String#scan

Например, строка:

'   hello "my name" is    "Tom"'

должна соответствовать словам:

hello
my name
is
Tom

Мне удалось сопоставить слова, заключенные вдвойные кавычки, используя:

/"([^\"]*)"/

, но я не могу понять, как включить окруженные пробелами символы, чтобы получить «привет», «есть» и «Том», в то же время не винтup 'my name'.

Любая помощь с этим будет признательна!

Ответы [ 3 ]

22 голосов
/ 17 ноября 2011
result = '   hello "my name" is    "Tom"'.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/)

будет работать для вас.Будет напечатано

=> ["", "hello", "\"my name\"", "is", "\"Tom\""]

Просто игнорируйте пустые строки.

Объяснение

"
\\s            # Match a single character that is a “whitespace character” (spaces, tabs, and line breaks)
   +             # Between one and unlimited times, as many times as possible, giving back as needed (greedy)
(?=           # Assert that the regex below can be matched, starting at this position (positive lookahead)
   (?:           # Match the regular expression below
      [^\"]          # Match any character that is NOT a “\"”
         *             # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
      \"             # Match the character “\"” literally
      [^\"]          # Match any character that is NOT a “\"”
         *             # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
      \"             # Match the character “\"” literally
   )*            # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
   [^\"]          # Match any character that is NOT a “\"”
      *             # Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
   \$             # Assert position at the end of a line (at the end of the string or before a line break character)
)
"

Вы можете использовать reject, чтобы избежатьпустые строки

result = '   hello "my name" is    "Tom"'
            .split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/).reject {|s| s.empty?}

печать

=> ["hello", "\"my name\"", "is", "\"Tom\""]
4 голосов
/ 17 ноября 2011
text = '   hello "my name" is    "Tom"'

text.scan(/\s*("([^"]+)"|\w+)\s*/).each {|match| puts match[1] || match[0]}

Производит:

hello
my name
is
Tom

Объяснение:

0 или более пробелов, за которыми следует

либо

некоторые слова в двойных кавычкахИЛИ

одно слово

, за которым следуют 0 или более пробелов

1 голос
/ 30 июля 2012

Вы можете попробовать это регулярное выражение:

/\b(\w+)\b/

, которое использует \b, чтобы найти границу слова.И этот веб-сайт http://rubular.com/ полезен.

...