Почему я получаю дополнительные неожиданные результаты с помощью моего регулярного выражения? - PullRequest
4 голосов
/ 14 апреля 2010

Я наконец изучаю регулярные выражения и тренируюсь с ack . Я считаю, что это использует Perl регулярное выражение.

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

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

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

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

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

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

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


РЕДАКТИРОВАТЬ добавление командной строки

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

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

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

274:                }else if (y != 0) 

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


РЕДАКТИРОВАТЬ добавить результат теста Мобрула

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, извините, что беспокою вас за это.

Ответы [ 3 ]

6 голосов
/ 14 апреля 2010
^\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|
4 голосов
/ 14 апреля 2010

В 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
1 голос
/ 14 апреля 2010

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

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

.

\t*| *

будет ноль или более табуляций или ноль или более пробелов, а не комбинация пробелов и табуляций.

...