2010-04-14 2 views
4

Я, наконец, изучаю регулярное выражение и обучение с помощью ack. Я считаю, что это использует Perl regexp.Почему я получаю дополнительные неожиданные результаты с помощью reckx ack?

Я хочу сопоставить все строки, где первые непустые символы: if (<word> !, с любым количеством пробелов между элементами.

Это то, что я придумал:

^[ \t]*if *\(\w+ *! 

Это только почти работал. ^[ \t]* неверен, так как он соответствует одному или никому [пробелу или табуляции]. Я хочу, чтобы соответствовать всем, что может содержать только пробел или вкладку (или ничего).

Например они не должны совпадать:

// if (asdf != 0) 
else if (asdf != 1) 

Как я могу изменить регулярное выражение для этого?


EDIT добавления Командная строка

ack -i --group -a '^\s*if *\(\w+ *!' c:/work/proj/proj 

Примечание одиночные кавычки, я не уверен, что о них больше.

Моя поисковая база - это большая база кода. Он включает соответствующие выражения (вполне некоторые), но даже, например:

274:    }else if (y != 0) 

, которые я получаю в результате указанной выше команды.


EDIT добавив результат теста mobrule в

Mobrule, спасибо за предоставленную мне текст, чтобы проверить на. Я скопирую здесь, что я получу по моему приглашению:

C:\Temp\regex>more ack.test 
# ack.test 
if (asdf != 0) # no spaces - ok 
if (asdf != 0) # single space - ok 
    if (asdf != 0) # single tab - ok 
    if (asdf != 0) # multiple space - ok 
     if (asdf != 0) # multiple tab - ok 
    if (asdf != 0) # spaces + tab ok 
    if (asdf != 0) # tab + space ok 
    if (asdf != 0) # space + tab + space ok 
// if (asdf != 0) # not ok 
} else if (asdf != 0) # not ok 

C:\Temp\regex>ack '^[ \t]*if *\(\w+ *!' ack.test 

C:\Temp\regex>"C:\Program\git\bin\perl.exe" C:\bat\ack.pl '[ \t]*if *\(\w+ *!' a 
ck.test 
if (asdf != 0) # no spaces - ok 
if (asdf != 0) # single space - ok 
    if (asdf != 0) # single tab - ok 
    if (asdf != 0) # multiple space - ok 
     if (asdf != 0) # multiple tab - ok 
    if (asdf != 0) # spaces + tab ok 
    if (asdf != 0) # tab + space ok 
    if (asdf != 0) # space + tab + space ok 
// if (asdf != 0) # not ok 
} else if (asdf != 0) # not ok 

Проблема заключается в моем призыве к моему ack.bat!

ack.bat содержит:

"C:\Program\git\bin\perl.exe" C:\bat\ack.pl %* 

Хотя я называю с кареткой, он уходит на вызове файла летучей мыши!

Экранирование каретки с помощью ^^ не работает.

Цитирование регулярного выражения " " вместо ' ' работ. Моя проблема была проблемой DOS/win, извините за то, что беспокоило вас всех за это.

+0

Как mobrule сказал в своем ответе, ваше регулярное выражение выглядит хорошо для желаемого поведения вы описали. Можете ли вы изменить свой вопрос, чтобы включить пример данных, командную строку ack, которую вы используете, и ваш желаемый результат? –

+0

Если вы еще этого не сделали, прочитайте perlrequick (man perlrequick, perldoc perlrequick или найдите его онлайн). После этого, если вы хотите более продвинутые возможности, прочитайте perlre. В любом случае, я настоятельно рекомендую освоить регулярные выражения от O'Reilly. – kbenson

ответ

4

В обоих ack и grep, * соответствует нулю или больше, а не нулю или одному. Поэтому я думаю, что у вас уже есть правильное решение. Какие тестовые примеры не дают вам желаемых результатов?

# ack.test 
if (asdf != 0) # no spaces - ok 
if (asdf != 0) # single space - ok 
    if (asdf != 0) # single tab - ok 
    if (asdf != 0) # multiple space - ok 
     if (asdf != 0) # multiple tab - ok 
    if (asdf != 0) # spaces + tab ok 
    if (asdf != 0) # tab + space ok 
    if (asdf != 0) # space + tab + space ok 
// if (asdf != 0) # not ok 
} else if (asdf != 0) # not ok 

Результаты:

$ ack '^[ \t]*if *\(\w+ *!' ack.test 
if (asdf != 0) # no spaces - ok 
if (asdf != 0) # single space - ok 
     if (asdf != 0) # single tab - ok 
    if (asdf != 0) # multiple space - ok 
       if (asdf != 0) # multiple tab - ok 
     if (asdf != 0) # spaces + tab ok 
     if (asdf != 0) # tab + space ok 
     if (asdf != 0) # space + tab + space ok 

$ ack -v '^[ \t]*if *\(\w+ *!' ack.test 
// if (asdf != 0) # not ok 
} else if (asdf != 0) # not ok 
+0

@mobrule - и главная страница ack, и вопрос OP указывают, что ack использует регулярное выражение Perl, а не grep. – DVK

+0

'} else if (y! = 0) {' в моих результатах. Обратите внимание, что я использую одиночную цитату вокруг выражения в командной строке, может ли это быть связано с моей проблемой? – Gauthier

6
^\s*if\s*\(\S+\s*! 
  • Использование \S для небелых пространства. \w не будет соответствовать специальным символам, поэтому if ($word не будет соответствовать.Может быть, это нормально с вашими спецификациями, в этом случае \w (буквенно-цифровой плюс "_" ) ОК
 
$ perl5.8 -e '{$s="else if (asdf \!= 1)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' 
NO MATCH 
$ perl5.8 -e '{$s="// if (asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' 
NO MATCH 
$ perl5.8 -e '{$s=" if (asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' 
|asdf| 
$ perl5.8 -e '{$s="if (asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' 
|asdf| 
$ perl5.8 -e '{$s="if (\$asdf \!= 0)"; if ($s =~ /^\s*if\s*\((\S+)\s*\!/) { print "|$1|\n";} else { print "NO MATCH\n";}}' 
|$asdf| 
+0

Пожалуйста, игнорируйте обратную косую черту перед символом «!». в моих примерах - это в пользу оболочки Unix. Внутренне в Perl это просто «!» – DVK

+0

То же самое здесь. Он просто выглядит как '^' не работает! – Gauthier

+0

И да, у меня был ack.bat где-то, и он, кажется, удаляет символ '^'! (см. мой отредактированный пост). – Gauthier

1

Вы можете попробовать:

(?:\t*| *)if *\(\w+ *! 

.

\t*| * 

будет содержать ноль или больше вкладок или ноль или больше пробелов, а не сочетание пробелов и вкладок.

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