#regex #multiline
Вопрос:
Я должен признать, что я очень прост, если дело доходит до выражений регулярных выражений. У меня есть приложение, написанное на C#, которое ищет определенные выражения регулярных выражений в текстовых файлах. Я не уверен, как объяснить свою проблему, поэтому перейду прямо к примеру.
Мое сообщение:
DeviceNr : 30
DeviceClass = ABC
UnitNr = 1
Reference = 29
PhysState = ENABLED
LogState = OPERATIVE
DevicePlan = 702
Manufacturer = CDE
Model = EFG
ready
DeviceNr : 31
DeviceClass = ABC
UnitNr = 9
Reference = 33
PhysState = ENABLED
LogState = OPERATIVE
Manufacturer = DDD
Model = XYZ
Description = something here
ready
Мне нужно сопоставить многострочный текст, который начинается со слова «DeviceNr», заканчивается «готово» и имеет «DeviceClass = ABC» и «Модель = XYZ» — я могу только предположить, что эти строки будут в таком точном порядке, но я не могу предположить, что будет между ними, даже количество других строк между ними. Я попытался использовать приведенное ниже регулярное выражение, но оно соответствовало всему тексту, а не только DeviceNr : 31
DeviceNr : ([0-9] )(?:.*?n)*? DeviceClass = ABC(?:.*?n)*? Model = XYZ(?:.*?n)*?readynn
Комментарии:
1. Это то, что ты ищешь?
(?=(DeviceNr.*?ready))
Демо: regex101.com/r/nZj7wS/22. Может быть, глупый вопрос, но как насчет той части, где мне нужно сопоставить строки «DeviceClass = ABC» и «Модель = XYZ» между «DeviceNr» и «готово» ?
3. Проверьте это:
(?=DeviceNr.*?(DeviceClasss=sw ).*?(Models=sw ).*ready)
Демонстрация: regex101.com/r/nZj7wS/34. Это все еще не дает мне того, в чем я нуждаюсь. regex101.com/r/MBXSht/1 Мне нужно, чтобы это было только одно совпадение (второе), мне нужно знать, что я сопоставил обе строки и что они помещены в «DeviceNr» и ПЕРВОЕ найденное «готовое» слово.
Ответ №1:
Если вы знаете, что "DeviceClass = ABC" and "Model = XYZ"
они присутствуют и в таком порядке, вы также можете использовать утверждение lookahead для каждой строки, сначала сопоставляя все строки, которые, например, не содержат DeviceNr
Затем сопоставьте строки, которые это делают, а также сделайте это для Model
и ready
^s*DeviceNr : ([0-9] )(?:r?n(?!s*DeviceClass =).*)*r?ns*DeviceClass = ABCb(?:r?n(?!s*Model =).*)*r?ns*Model = XYZb(?:r?n(?!s*ready).*)*r?ns*readyb
^
Начало строкиs*DeviceNr : ([0-9] )
СопоставьтеDeviceNr :
и зафиксируйте 1 цифры 0-9 в группе 1(?:
Группа без захватаr?n(?!s*DeviceClass =).*
Сопоставьте новую строку и подтвердите, что строка не содержитDeviceClass =
)*
Закройте группу без захвата и при необходимости повторите, так как вы не знаете, сколько там строкr?ns*DeviceClass = ABCb
Сопоставьте новую строку, необязательные символы пробелов иDeviceClass = ABC
(?:r?n(?!s*Model =).*)*r?ns*Model = XYZb
Предыдущий подход также дляModel =
(?:r?n(?!s*ready).*)*r?ns*readyb
И тот же подход кready
Демонстрация регулярных выражений
Обратите внимание, что s
это также может соответствовать новой строке. Если вы хотите предотвратить это, вы также можете использовать [^Srn]
для сопоставления символа пробела без новой строки.
Комментарии:
1. Спасибо! и спасибо за объяснение, это очень сложный шаблон, но он делает то, что мне нужно.
Ответ №2:
Вопрос в том, что вы хотите, чтобы соответствовать ‘DeviceNr : 31’ следует ‘DeviceClass = АВС (возможно с одной из промежуточных символов), а затем модель’ = Хуг (опять же, возможно, с одной из промежуточных символов), затем «Готово» (опять же, возможно, с одной из промежуточных символов) , убедившись, что никто из лиц, выступающих персонажей на самом деле являются началом другого ‘DeviceNr разделе.
Таким образом, чтобы сопоставить произвольные промежуточные символы с приведенным выше применением, мы можем использовать следующее регулярное выражение, в котором используется отрицательное утверждение lookahead:
(?:(?!DeviceNr)[sS])*?
(?:
— Начало группы без захвата(?!DeviceNr)
— Утверждает, что следующие символы ввода не являются «DeviceNr»[sS]
— Соответствует пробелу или символу без пробелов, т. е. любому символу)
конец группы без захвата*?
не жадно сопоставляйте 0 или более символов до тех пор, пока следующий ввод не будет соответствовать «DeviceNr».
Тогда очень просто использовать приведенное выше регулярное выражение повторно следующим образом:
DeviceNr : (d )n(?:(?!DeviceNr)[sS])*?DeviceClass = ABCn(?:(?!DeviceNr)[sS])*?Model = XYZn(?:(?!DeviceNr)[sS])*?ready
Смотрите Демонстрацию регулярных выражений
Группа захвата 1 будет иметь DeviceNr
значение.
Важное Примечание
Приведенное выше регулярное выражение довольно дорого с точки зрения количества шагов, необходимых для выполнения, поскольку оно должно проверять отрицательное утверждение lookahead практически в каждой позиции символа, как только оно совпадет DeviceNr : (d )
.