Как я могу использовать регулярное выражение для сопоставления чего-либо в форме "stuff = foo" "stuff" = "вещи" - PullRequest
1 голос
/ 27 мая 2010

Мне нужно регулярное выражение, чтобы сопоставить что-то вроде этого,

'текст' | «текст» | ... | 'текст' (~ текст) = 'текст' | «текст» | ... | 'Текст'

Я просто хочу разделить его на две части: часть слева от знака равенства и часть справа. Любая из «текстовых» записей может иметь «=» между «символами». Я думал о том, чтобы попытаться сопоставить четное число с последующим символом =, но я не уверен, как сопоставить четное число чего-либо. Также обратите внимание, что я не знаю, сколько записей с обеих сторон может быть , Пара примеров,

'51NL9637X33' | 'ISL6262ACRZ-T' | 'QFN' (~ 51NL9637X33) = '51NL9637X33' | 'ISL6262ACRZ-T' | "ИНТЕРСИЛЬ" | 'QFN7SQ-HT1_P49' | '()'

Должен извлечь, '51NL9637X33' | 'ISL6262ACRZ-T' | 'QFN' (~ 51NL9637X33) а также, '51NL9637X33' | 'ISL6262ACRZ-T' | "ИНТЕРСИЛЬ" | 'QFN7SQ-HT1_P49' | '()'

'227637' | 'SMTU2032_1' | 'SKT W / BAT' (~ 227637) = '227637' | 'SMTU2032_1' | 'РЕНАТА' | 'SKT28_5X16_1-HT5_4_P2' | '()': SPECIAL_A = 'BAT_CR2032', PART_NUM_A = '202649'

Должен извлечь, '227637' | 'SMTU2032_1' | 'SKT W / BAT' (~ 227637) а также, '227637' | 'SMTU2032_1' | 'РЕНАТА' | 'SKT28_5X16_1-HT5_4_P2' | '()': SPECIAL_A = 'BAT_CR2032', PART_NUM_A = '202649'

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

Ответы [ 3 ]

4 голосов
/ 27 мая 2010

На самом деле я бы вообще не использовал регулярные выражения для этого. Предполагая, что на вашем языке есть операция split, я бы сначала разделил символ |, чтобы получить список:

'51NL9637X33'
'ISL6262ACRZ-T'
'QFN'(~51NL9637X33) = '51NL9637X33'
'ISL6262ACRZ-T'
'INTERSIL'
'QFN7SQ-HT1_P49'
'()'

Затем я бы разделил каждого из них на символ =, чтобы получить ключ и (необязательно) значение:

'51NL9637X33'           <null>
'ISL6262ACRZ-T'         <null>
'QFN'(~51NL9637X33)     '51NL9637X33'
'ISL6262ACRZ-T'         <null>
'INTERSIL'              <null>
'QFN7SQ-HT1_P49'        <null>
'()'                    <null>

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

0 голосов
/ 27 мая 2010

Как сказал paxdiablo, вы почти наверняка не хотите использовать здесь регулярное выражение. Предложение split неплохое; Я сам, вероятно, использовал бы здесь парсер & mdash; есть много структур для использования. Идея заключается в том, что вы формально определяете синтаксис того, что у вас есть - что-то вроде того, что вы нам дали, только строго. Так, например: field - это последовательность символов, не заключенных в одинарные кавычки, заключенные в одинарные кавычки; fields - любое число field с, разделенных пробелом, a | и больше пробелов; tilde - символы без скобок, окруженные (~ и ); expr - это fields, необязательный пробел, необязательный tilde, =, необязательный пробел и еще один fields. То, как вы это выражаете, зависит от языка, который вы используете. Например, в Haskell, используя библиотеку Parsec, вы пишете каждый из этих анализаторов следующим образом:

import Text.ParserCombinators.Parsec

field :: Parser String
field = between (char '\'') (char '\'') $ many (noneOf "'\n")

tilde :: Parser String
tilde = between (string "(~") (char ')') $ many (noneOf ")\n")

fields :: Parser [String]
fields = field `sepBy` (try $ spaces >> char '|' >> spaces)

expr :: Parser ([String],Maybe String,[String])
expr = do left <- fields
          spaces
          opt  <- optionMaybe tilde
          spaces >> char '=' >> spaces
          right <- fields
          (char '\n' >> return ()) <|> eof
          return (left, opt, right)

Точное понимание того, как работает этот код, не очень важно; основная идея состоит в том, чтобы разбить то, что вы анализируете, выразить это в формальных правилах и создать его обратно из меньших компонентов. И для чего-то подобного это будет намного чище, чем регулярное выражение.


Если вы действительно хотите получить регулярное выражение, вот, пожалуйста (едва протестировано):

^\s*('[^']*'((\s*\|\s*)'[^'\n]*')*)?(\(~[^)\n]*\))?\s*=\s*('[^']*'((\s*\|\s*)'[^'\n]*')*)?\s*$

Видишь, почему я рекомендую парсер? Когда я впервые написал это, я понял по минимум две вещи, которые я подобрал (по одной на тест), и, вероятно, есть что-то еще. И я не вставлял группы захвата, где вы хотели их, потому что я не знал, куда они пойдут. Теперь да, я мог бы сделать это более читабельным, вставив комментарии и т. Д. И в конце концов, regexen имеет свое применение! Однако дело в том, что это не один из них. Палка с чем-то лучше.

0 голосов
/ 27 мая 2010

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

Вопрос "Как мне сопоставить четное количество символов?" Тем не менее, это интересно, и вот как я бы это сделал в вашем случае:

(?:'[^']*'|[^=])*(?==)

Это выражение соответствует левой части вашей записи, ища ' в его текущей позиции. Если он находит один, он переходит к следующему ' и, таким образом, соответствует только четному количеству кавычек. Если он не находит ', он соответствует чему-либо, что не является знаком равенства, а затем гарантирует, что знак равенства следует за соответствующей строкой. Это работает, потому что механизм регулярных выражений оценивает конструкции OR слева направо.

Вы можете получить левую и правую части в двух группах захвата, используя

((?:'[^']*'|[^=])*)=(.*)

Я рекомендую http://gskinner.com/RegExr/ для работы с регулярными выражениями. =) * * 1016

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...