2015-03-23 3 views
0

Я ищу в файле строки, которые не заканчиваются обратной косой чертой (\), но они должны начинаться с некоторого текста, поэтому я написал:Поиск строк, которые не заканчиваются заданным символом

if ($cur_line =~ m{\A\s+(.+?)(?!\\)\z/xms){ 
... # parentheses are only for testing 
} 

Но с приведенным выше $1 всегда содержит всю строку (без пробелов), включая обратную косую черту в конце. Только первое вхождение строки без обратного слэша в конце соответствует правильно. После этого все линии с задней задней косой чертой совпадают. Зачем? Что я делаю не так?

Когда я использую:

if ($cur_line =~ m{\A\s+[^\\]+(?!\\)\z/xms){ 
... 
} 

он работает почти правильно, однако $cur_line затем может содержать обратную косую черту.

Я проверил следующий код:

if ($cur_line !~ m{\\\z}xms) { 

драм он прекрасно работает. Но мне любопытно, что не так с моим негативным взглядом.

+1

a lookahead смотрит вперед * (означает «следует за») *, поскольку следующий токен в вашем шаблоне - это '\ z' anchors * (конец строки) *,' (?! \\) \ z 'всегда верно! (в конце строки нет слэша, так как это конец строки). Чтобы проверить последний символ перед концом строки, попробуйте lookbehind '(?

ответ

1

вы могли бы использовать этот шаблон, если ваш двигатель поддерживает отрицательный взгляд-за

\A\s+(.*)(?<!\\)\z 

или этот шаблон, если он не

\A\s+(.*[^\\])\z 

причина, почему ваш первый шаблон не работает, потому что (.+?) уже уничтожил последнюю косую черту, а последняя обратная косая черта не видна \

+0

Я думал, что понимаю регулярное выражение, но я ошибся. Оба шаблона работают даже без '?' – piecia

0

Кажется, ghtforward, чтобы написать именно то, что вы описали. Вы просили «» строки, которые не заканчиваются на обратную косую черту, но они должны начинаться с некоторого текста «.

Это ищет конец строки \z, которому не предшествует обратная косая черта (?<!\\) (обратная косая черта должна быть дублирована). И второе регулярное выражение проверяет, что в строке есть непространственный символ.

for ('abcdef\\', 'abcdef', '\\', '') { 
    printf "'%s' -- %s\n", $_, /(?<!\\)\z/ && /\S/ ? 'match' : 'no match'; 
} 

выход

'abcdef\' -- no match 
'abcdef' -- match 
'\' -- no match 
'' -- no match 

Учтите, что проверка на вещи в конце линии может оказаться под вопросом из-за символ новой строки, так что вы должны chomp каждую строку, прежде чем проверить. Вам решать, что делать с линиями, которые заканчиваются, скажем, обратным слэшем, а затем пробелами.

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