Как получить линии, основанные на определенной модели?

8

Допустим, у меня есть файл, содержащий следующие две строки:

2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
2014-05-05      09:12:17    /aa/bbbb/cccccc?dddddddd    16767 

Мне нужно , чтобы получить строку , содержащую образец /aa/bbbb/ccccccтолько, мне не нужен второй строки , содержащие дополнительные символы , то есть ?dddddddd. Теперь, когда я пытался

grep '/aa/bbbb/cccccc' file

Затем обе линии выбираются. Мне нужна полная строка, поэтому grep -oне может быть решением.

Что может быть возможным решением с использованием grep, чтобы только первая строка была выбрана на основе шаблона поиска?

heemayl
источник

Ответы:

7

Попробуйте приведенную ниже команду grep, которая использует параметр -P( Perl-regexp ).

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S)Этот негативный взгляд утверждает, что символ, который предшествует строке /aa/bbbb/cccccc, будет любым, но не пробелом.

  • (?!\S) Отрицательный взгляд утверждает, что символ, следующий за совпадением, будет любым, но не пробелом.

Еще один grep,

 grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file

Через питона,

script.py

#!/usr/bin/python3
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        for i in line.split():
            if i == "/aa/bbbb/cccccc":
                print(line, end='')

Сохраните приведенный выше код в файле и назовите его как script.py. Затем выполните приведенный выше сценарий

python3 script.py /path/to/the/file/you/want/to/work/with
Авинаш Радж
источник
Спасибо чувак. Кстати, это можно сделать с помощью обычного / расширенного регулярного выражения, а не регулярного выражения perl?
Heemayl
1
Как Terdon опубликовал, вы могли бы простоgrep '/aa/bbbb/cccccc ' file
Avinash Радж
Но выше не будет печатать строки, которые имеют только /aa/bbbb/ccccccстроку.
Авинаш Радж
Вы можете сопоставить это тоже сgrep -E '/aa/bbbb/cccccc(\s+|$)' file
Terdon
да, вот такgrep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file
Авинаш Радж
10

Самый простой способ - добавить пробел после вашего шаблона:

$ grep '/aa/bbbb/cccccc ' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Или, чтобы соответствовать всем видам пробелов:

$ grep  '/aa/bbbb/cccccc[[:space:]]' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Или

$ grep -P '/aa/bbbb/cccccc\s+' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Или с положительным взглядом :

$ grep -P '/aa/bbbb/cccccc(?=\s)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Или с отрицательным взглядом :

$ grep -P '/aa/bbbb/cccccc(?!\S)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Или вы можете отменить матч:

$ grep  -v 'c?' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Или, чтобы также соответствовать линиям, которые не содержат ничего, кроме вашего шаблона (без пробелов):

grep -P '/aa/bbbb/cccccc(\s+|$)' file 
grep -E '/aa/bbbb/cccccc(\s+|$)' file 

Или вы можете просто использовать небольшой скрипт:

  • В awk:

    $ awk '$3=="/aa/bbbb/cccccc"' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

    Или, если вы не знаете, в каком поле находится ваш паттерн

    $ awk '{for(i=1;i<=NF;i++){if($i=="/aa/bbbb/cccccc"){print}}}' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
  • В Perl

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
terdon
источник
@terdon, grep -v 'c?' fileпочему вы не используете, grep -v '?' fileпотому что файл имеет только две строки.
αғsнιη
@KasiyA правда, я просто хотел сохранить немного картины. Вы совершенно правы, хотя, в данном конкретном случае, grep -v '?'будет достаточно.
тердон
2

В дополнение к @AvinashRaj «s ответ , вы также можете использовать команду , как это.

grep -P '/a+/b+/c+(?!\S)' file
αғsнιη
источник