2010-10-13 2 views
0

Я пытаюсь выяснить, как лучше разобрать строки текста, которые имеют значение, которые выглядят следующим образом:Разбор Линии отдельных слов и групп слов в кавычках с помощью регулярных выражений в Ruby,

line1 
'Line two' fudgy whale 'rolly polly' 
fudgy 'line three' whale 
fudgy whale 'line four' 
'line five' 'fish heads' 
line six 

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

Желаемая выход:

["line1"] 
["Line two", "fudgy", "whale", "rolly polly"] 
["fudgy", "line three", "whale"] 
["fudgy", "whale", "line four"] 
["line five", "fish heads"] 
["line", "six"] 

Показание линии уже обрабатывается для меня через огурец. Каждая строка считывается как одно строковое значение, и я хочу разобрать отдельные слова и любое количество слов, содержащихся в одинарных кавычках. Я знаю меньше, чем ничего о регулярных выражениях, но я скопировал регулярное выражение, используя регулярное выражение «или» operator («|»), которое закрыло меня.

Принимая, что регулярное выражение я сначала пытался разбора каждой строки с использованием строки раскол:

text_line.split(/(\w+)|'(.*?)'/) 

который привел к следующему, менее чем приемлемые, массивы:

["", "line1"] 
["", "Line two", " ", "fudgy", " ", "whale", " ", "rolly polly"] 
["", "fudgy", " ", "line three", " ", "whale"] 
["", "fudgy", " ", "whale", " ", "line four"] 
["", "line five", " ", "fish heads"] 
["", "line", "", "six"] 

Затем я попытался с помощью сканирования вместо и я увидел это:

text_line.scan(/(\w+)|'(.*?)'/) 
[["line1", nil]] 
[[nil, "Line two"], ["fudgy", nil], ["whale", nil], [nil, "rolly polly"]] 
[["fudgy", nil], [nil, "line three"], ["whale", nil]] 
[["fudgy", nil,], ["whale", nil], [nil, "line four"]] 
[[nil, "line five"], [nil, "fish heads"]] 
[["line", nil], [nil, "six",]] 

Так что я мог видеть регулярное выражение "или" оператора создавала ценность для каждой возможной «или» позиции, которая имела смысл. Зная, что я понял, я мог бы использовать сканирование, сглаживаются, и компактен, чтобы очистить его дать мне желаемый результат:

text_line.scan(/(\w+)|'(.*?)'/).flatten.compact 
["line1"] 
["Line two", "fudgy", "whale", "rolly polly"] 
["fudgy", "line three", "whale"] 
["fudgy", "whale", "line four"] 
["line five", "fish heads"] 
["line", "six"] 

Но с помощью сканирования, сглаживаются, и компактный выглядит невероятно уродливый и кажется, что я «Просто обезьяна исправляет мое собственное плохое регулярное выражение. Я думаю вместо того, чтобы ham-handedly фиксировать неаккуратный вывод из моего плохо сконструированного регулярного выражения, я должен просто написать лучшее регулярное выражение.

Итак, Можно ли использовать одно регулярное выражение для синтаксического анализа вышеуказанных строк и получения желаемого результата? Я могу начать с регулярного выражения, но я думаю, могу ли я как-то сгруппировать их или так, чтобы они возвращали только одно значение для каждой группы, что, вероятно, было бы тем, что я ищу.

Пожалуйста, не стесняйтесь предлагать альтернативные решения, но Я ищу элегантные решения, выполненные Ruby way, так как я пытаюсь научить себя, как использовать язык.

Заранее благодарим за ваше время.

отредактированный включать tininfi более лучшее, более точное регулярное выражение

+0

О, это слишком долго, чтобы прочитать все ваши описания, не могли бы вы сделать это проще? Вы хотите извлекать все * слова, содержащиеся в одинарных кавычках * в каждой строке? – Vantomex

+0

Или просто произнесите слова «желаемый результат» полужирный – Nakilon

+0

Если я был слишком многословным, извиняюсь. Я уже заявил в своем тексте, что мой желаемый результат, но скопировал его на верх, чтобы сделать его более понятным. Причина, по которой я этого не делал, заключалась в том, что я хотел, чтобы люди помогали читать то, что я уже пробовал, поэтому они не тратят время на повторение этого. Кроме того, поскольку я описываю, что я ищу в конце вопроса, если вы не прочитаете весь вопрос, вы не поймете, о чем я прошу. – 2010-10-13 19:27:31

ответ

0

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

'(.*?)'|(\w+) 

Вы все еще должны использовать сглаживаются и компактный, но, по крайней мере, это немного лучше выглядит. Не то, что вы указали на необходимость, но это позволит строки:

'quote one' 'quote two' 

Ниже был отвергнут как менее элегантно, чем оригинальное решение.
Вы можете попробовать:

regex = %r((\w+)|(?:')([^"\r\n]*)(?:')) 
text.split(regex).delete_if { |x| x.strip.empty? } 

+0

Благодарим вас за усилия. Это на самом деле менее элегантно, чем решение, которое я уже придумал; основное внимание в моем вопросе заключается в том, как написать лучшее регулярное выражение. Спасибо за попытку. – 2010-10-13 23:08:03

+0

Вы получили ответ. Вы не только исправили ошибку в моем регулярном выражении, вы сделали код чище. И да, более элегантный. Теперь, если мне удастся пройти несколько месяцев, не сказав этого снова ... – 2010-10-14 09:08:54

+0

Хорошо, я рад, что это помогло. Мне все еще хотелось бы найти решение, которое не требует сглаживания и компактности. Спасибо, что помогли мне получить мои первые несколько баллов. Счастливое кодирование! – tinifni

1

Если вы хотите, чтобы получить массив массивов разного размера, вы можете сделать это в два этапа: .split и .scan. В вашем случае .scan имеет () с двух сторон от |, поэтому у вас есть проблемы с nil (что должно быть полезно, но не ваше дело). Таким образом, вы либо используете .flatten.compact, либо добавьте 3-й шаг .delete.

text.split("\n").map{|i|p i.scan(/'([^']+)'|(\w+)/).flatten.compact} 
text.split("\n").map{|i|p i.scan(/'[^']+'|\w+/).map{|i|i.delete "'"}} 
+0

Спасибо за ваш ответ. Ты покрываешь землю, которую я уже использую или отвергаю. Мое основное внимание уделяется выполнению самого «правильного» Ruby, который позволяет избежать неаккуратного программирования, которое я использую сейчас. Тем не менее, я очень благодарен за ваше время и усилия. – 2010-10-13 19:14:47

0

У меня есть ощущение, что вы все еще не нравится, но это ближе всего к «один регулярное выражение» Я мог бы придумать с:

Это прерывается, если входной текст имеет цитированное слово, которое начинается с пробела.

Смежные вопросы