2010-03-19 2 views
4

Я пытаюсь найти каждый шаблон «a -> b, c, d» во входной строке. Узор я использую следующее:EOL Special Char не соответствует

"^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$" 

Эта модель представляет собой C# шаблон, то «\ т» относится к табулирования (его единственный спасся litteral, intepreted с помощью API .NET String), то «\ w» ссылается на хорошо известный регулярный регулярный литерный класс, двойное экранирование которого интерпретируется как «\ w» .NET STring API, а затем как «WORD CLASS» API .NET Regex.

вход является:

a -> b 
b -> c 
c -> d 

Функция:

private void ParseAndBuildGraph(String input) { 
    MatchCollection mc = Regex.Matches(input, "^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$", RegexOptions.Multiline); 
    foreach (Match m in mc) { 
     Debug.WriteLine(m.Value); 
    } 
} 

Выход:

c -> d 

На самом деле, существует проблема с конца строки "$" специальный знак. Если я вставляю «\ r» перед «$», он работает, но я думал, что «$» будет соответствовать любому завершению строки (с опцией Multiline), особенно \ r \ n в среде Windows. Разве это не так?

ответ

7

Это удивило меня. В регулярных выражениях .NET $ не соответствует перед разделителем строк, он соответствует до linefeed - символ \n. Такое поведение согласуется с ароматом регулярного выражения Perl, но, по-моему, это все еще неправильно. According to the Unicode standard, $ должны соответствовать перед любым из:

\n, \r\n, \r, \x85, \u2028, \u2029, \v или \f

... и никогда не совпадают между \r и \n. Java соответствует этому (за исключением \v и \f), но .NET, который вышел долго после Java, а поддержка Unicode по крайней мере так же хороша, как Java, распознает только \n. Вы думаете, что они, по крайней мере, будут обрабатывать \r\n, учитывая, насколько сильно Microsoft связана с этим разделителем строк.

Имейте в виду, что . по той же схеме: он не соответствует \n (если режим SingleLine не установлен), но делает матч \r. Если вы использовали .+ вместо \w+ в своем регулярном выражении, возможно, вы не заметили эту проблему; возврат каретки был бы включен в игру, но консоль проигнорировала бы ее при печати результатов.

EDIT: Если вы хотите разрешить возврат каретки без включения ее в свои результаты, вы можете заменить якорь на смотровой: (?=\r?\n.

+1

+1 Трудно поверить ... –

+0

Благодарим вас за ответ. И действительно, это удивительный вывод :) –

+0

Любопытно, есть ли флаг, который можно настроить так, чтобы система соответствовала данным, например, флаг O_BINARY в c/C++. – Dave

1

Вы имеете в виду \t в качестве регулярного выражения \t или C# \t? Я всегда использую дословные строковых литералов регулярных выражений:

@"^[ \t]*(\w+)[ \t]*->[ \t]*(\w+)(,[ \t]*\w+)*$" 

(единственное, что вам нужно бежать в " к "")

+0

Фактически \ t относится к табуляции. Я не хочу использовать \\ s для символа пробела, так как я не хочу, чтобы пользователь вводил окончание строки, допускаются только пробелы и табуляции. Но мой вопрос остается тем же самым с упрощенным рисунком «^ (\\ w +) -> (\\ w +) ((?:, \\ w +) *) $". Я обновил исходный вопрос. –

+0

@ Aurélien - да, но без дословного строкового литерала регулярное выражение не видит '\ t' at * all *.

+0

@Marc Gravell - это вкладка или пробел, если регулярное выражение не позволяет встроенные вкладки, он буквально означает символ табуляции, а не \ t – Guvante

1

Обычно в C, C++, C#, строки в программе используют «\ n» в качестве разделителя строк. «\ r \ n» появляется только на уровне ввода/вывода, если текстовые переводы включены.

+0

Хорошая точка. Меня всегда удивляло, как редко возникает этот вопрос, и я думаю, что это одна из причин. Но я все же думаю, что они ошибались, чтобы не пойти со стандартом Unicode. –

+0

\ r \ n - это завершение линии Microsoft. Например, Notepad.exe не распознает «\ n» завершение и только распознает «\ r \ n». Для пользователей Unix «\ n» - обычное завершение строки, а для пользователей Mac - «\ r». Это глупый беспорядок? Я согласен :-) –

+0

\ r \ n - это терминатор линии (в Windows) в текстовом файле. \ n - это терминатор в коде. Уровень ввода-вывода переводит между ними тогда и только тогда, когда вы открываете файл в «текстовом режиме». –

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