2013-03-07 2 views
4

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

Например, я хочу, чтобы иметь возможность найти:

$10,000,000 to $20M 
$10k-$20k 
100.23k - 200.34k 
$20000 and $500600 
3456646 to 4230405 

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

$10,0000,000 to $20,000,000 //extra zero in first number 
20k xyz 40k //middle string does not match a range word 

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

(^|\s|\$)([1-9](?:\d*|(?:\d{0,2})(?:,\d{3})*)(?:\.\d*[1-9])?|0?\.\d*[1-9]|0)(|m|k)(?:|\s)(?:|to|and|-|,)(?:|\s)(|\$)([1-9](?:\d*|(?:\d{0,2})(?:,\d{3})*)(?:\.\d*[1-9])?|0?\.\d*[1-9]|0)(\s|m|k) 

Кажется, что он работает достаточно хорошо, но иногда соответствует элементам, которых я не ожидаю. Примеры:

1985 xyz 1999 //2 matches, both numbers without xyz 
$10,000,000 xyz $20000000 //1 match on the $2000000 
$10,000,0000 to $20,000,000 //1 match on the $10,000,0000 (extra zero on end) 

Что мне не хватает? Неразумно ли это делать с помощью регулярного выражения?

+6

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

+0

@Pieter Да, у меня было ощущение, что это слишком долго. Трудно отступить от него, если вы чувствуете себя так близко. Может быть, я попробую зачистить запятые раньше времени, и это упростит это. – robr

+0

Но что может быть быстрее: писать (и исследовать и тестировать) регулярное выражение, или просто писать простой парсер? –

ответ

2

Держи дружище

(?<=^|\s)\$?\d+((\.\d{2})?(k|M)|(,\d{3})*)\b\s*(to|-|and)\s*\$?\d*((\.\d{2})?(k|M)|(,\d{3})*)(\s|$) 

увидеть его в action.

Эта часть

\d+((\.\d{2})?(k|M)|(,\d{3})*) 

повторяется. Поэтому лучше сохранить это в постоянном и concat это регулярное выражение вместе.

String moneyPattern = @"\d+((\.\d{2})?(k|M)|(,\d{3})*)"; 
String rangeConnectorPattern = @"\b\s*(to|-|and\b)\s*"; 
String moneyRangePattern = @"(?<=^|\s)"+ 
    moneyPattern + rangeConnectorPattern + moneyPattern + 
    "(\s|$)"; 

Не нужно писать парсер.