Цепные (закачиваемые) greps игнорируют метасимволы? - PullRequest
1 голос
/ 10 ноября 2011

У меня проблемы с поиском строк с . в сложных (цепочечных) командах grep.
Это моя ошибка или ошибка?

grep '\.' filename | grep 1    # works correctly (finds lines with '.' and '1')
grep 1 filename | grep '\.'    # fails: ignores 2nd grep, returns lines with or without '.'

Это не канал, который вызывает это;это действительно что-то о grep.
Это откровенно кажется неправдоподобным, но это правда:

cat filename | grep 1 | grep '\.'   # works correctly (and provides an easy work-around for the bug)

Добавление дополнительной защиты не помогает:

grep 1 filename | grep '\\.'      # fails

Если есть что-топозади или перед символом подстановки, это работает:

grep 1 filename | grep 'a\.'     #  works
grep 1 filename | grep '\.a'     #  works

Но не, если что-то находится в диапазоне:

grep 1 filename | grep '[0-9]\.'    # fails
grep 1 filename | grep '\.[0-9]'    # fails

Я не могу поверить, что это действительно ошибка - ядолжно быть чего-то не хватает, верно?

Спасибо!

uname -a
Linux conception 2.6.32-33-generic #70-Ubuntu SMP Thu Jul 7 21:09:46 UTC 2011 i686 GNU/Linux

Ответы [ 2 ]

1 голос
/ 11 ноября 2011

Прежде всего, команда "цепочка" grep это что-то вроде "mauvais ton". В большинстве случаев grep | grep можно заменить одним grep со сложным регулярным выражением.

Стрижка строк с . и 1 в нем.

$> cat ./text | grep -P "(\..*1|1.*\.)"
line with 1 and . in it

-P означает регулярное выражение Perl "(\..*1|1.*\.)" - это (., некоторые символы и 1) или (1, некоторые символы и .)

Так что, если вы не совсем уверены в использовании подстановочных знаков, регулярные выражения могут быть вашим полезным, безопасным и мощным инструментом.

$> cat ./text 
line without anything
another line
line with.ok
and one another
line with 1
some text

line with 1 and . in it
empty line
last line

Первые примеры grep '\.' filename | grep 1, grep 1 filename | grep '\.', cat filename | grep 1 | grep '\.' возвращает правильный ответ

line with 1 and . in it

Второй пример grep 1 filename | grep '\\.' не удался, потому что вы набираете \ с любым символом после него.

0 голосов
/ 11 ноября 2011

Моя глупая ошибка.

Я собирал кучу файлов, а само имя файла содержало символ '.':

cat one.file
    1
    2
    3

cat second.file  
    10  
    11  
    12.  

Теперь

grep 1 *file | grep '\.'

  one.file: 1  
  second.file: 10  
  second.file: 11  
  second.file: 12.  

Я посмотрел на вывод и подумал, что 2-й grep игнорируется. Теперь очевидно, что происходит, но я действительно бросил это утро.

...