Разбор строки - есть ли более эффективный метод, чем проверка каждой строки? - PullRequest
3 голосов
/ 11 февраля 2012

Я работаю над проектом, чтобы разобрать текстовый файл. Файл выводится из сетевого оборудования. Длина входящей строки составляет от нескольких тысяч до десятков тысяч строк. Там будет переменное количество записей с такими ключевыми словами, как эти:

fcN/N is up
   Hardware is Fibre Channel, SFP is short wave laser w/o OFC (SN)
   Port WWN is 20:52:00:0d:ec:ef:b0:40
    Admin port mode is F, trunk mode is on
    snmp link state traps are enabled
    Port vsan is 10

fcipN is up
.....

port-channel-N is trunking
...... 

N - это число. Всегда будут записи 'fcN / N', могут быть или не быть две другие. Записи 'fcip' и 'port-channel' после каждой будут иметь информацию о статусе, аналогичную записям fcN / N. Все записи одного и того же типа будут сгруппированы - не будет fc, ​​за которым следует fcip, за которым следует другой fc. Также, как правило, перечислены все записи fc, затем все port-channel, затем все fcip, но я не хочу этого допускать. На данный момент у меня есть около 7 различных шаблонов RegEx, которые я ищу. Я делаю это, рассматривая каждую строку по очереди, однако управлять всеми этими функциями громоздко. Я думал о том, чтобы разбить строку на новую строку, а затем выбрать какой-то тип LINQ, чтобы получить все записи каждого из трех типов, но это предполагает, что они всегда группируются в одном и том же порядке. Я также подумал о трех регулярных выражениях монстров, чтобы соответствовать всему от одной записи к другой, но мой опыт таков, что трудно работать и почти нечитаемо. Еще одна вещь, о которой я подумал: сначала сопоставьте три ключевых слова - fc или port-channel или fcip, а затем оператор if, соответствующий шаблонам, уникальным для них. Это все еще соответствует каждой строке для всех 3 паттернов.

Чтобы было ясно, у меня работают шаблоны Regex. Я ищу более эффективный способ сделать это, чем проверять каждую строку на 6 0r 8 совпадений.

Есть еще идеи?

Ответы [ 3 ]

0 голосов
/ 11 февраля 2012

Вы можете получить более четкий и краткий код с помощью библиотеки комбинатора синтаксического анализатора, такой как Sprache .

Не будучи программистом на C #, я не очень хорошо знаком с этой библиотекой (и вполне могут быть и другие для C #), но я использовал комбинаторы синтаксического анализатора Scala для хорошего эффекта, и они основываются и используют обычные Разбор выражения.

Повышение эффективности вашего кода зависит от того, насколько неэффективен ваш код сейчас.

0 голосов
/ 11 февраля 2012

Вы ищете грубую скорость или эффективность? Если первое, вы можете разбить файл на части и иметь поток, анализирующий каждую часть одновременно. Хитрость заключается в том, чтобы быстро найти границу для разделения (так, чтобы каждая часть содержала только целые записи). Вы также захотите использовать многопоточность только в том случае, если общее количество строк велико, или издержки перевесят выгоды от распараллеливания.

0 голосов
/ 11 февраля 2012

У меня две мысли:

(1) Ваш последний подход к использованию операторов if для нахождения правильного регулярного выражения для применения - это достаточно эффективный метод. Я бы порекомендовал это.

(2) Вы можете составить регулярное выражение следующим образом:

var pattern1 = @"abc";
var pattern2 = @"def";
var unionPattern = "((" + pattern1 + ")|(" + pattern2 + "))";

Это делает его намного более читабельным.

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

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

var chunks = Regex.Split(str, "((fc\d)|(fcip\d)|(port-channel-\d)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...