Как обрабатывать несколько строк как один результат в grep или, по крайней мере, фильтровать без изменения - PullRequest
0 голосов
/ 09 января 2019
grep -A5 -E 'L337' -E 'Blue' -E 'Honda' -E 'Height: 6'  ./vehicles

Используя этот код bash, я отфильтровал сотни результатов до 13, как показано ниже:

License Plate L337ZR9
Make: Honda
Color: Red
Owner: Katie Park
Height: 6'2"
Weight: 189 lbs

Я пытаюсь отфильтровать сначала по пластине, а затем удалить любой не синий, а не хонда, и любой короче 6 '. Мой синтаксис неверен, и я могу только вернуть это или любую отдельную строку, соответствующую любому из условий поиска.

Использование -v имеет две проблемы: во-первых, непрактично фильтровать по каждому минусу, когда у меня есть точные позитивы для поиска, а во-вторых,

grep -v 'Height: 5'

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

Как я могу отфильтровать результаты с помощью grep, сохранив все 6 строк? Можно ли указать построчный фильтр?

-

Edit: файл выглядит так, только я уже grep-ed для 'L337' на пластине. Проблема в том, что у меня проблемы с обработкой 6 отдельных строк данных как одной 6-строчной записи. -A5 позволяет мне вернуть 5 строк под номерным знаком, но я не знаю, как найти «синий», не вырезая номерной знак и не убирая сверху.

License Plate L337DV9
Make: Honda
Color: Blue
Owner: Joe Germuska
Height: 6'2"
Weight: 164 lbs
--
License Plate L3375A9
Make: Honda
Color: Blue
Owner: Jeremy Bowers
Height: 6'1"
Weight: 204 lbs
--
License Plate L337WR9
Make: Honda
Color: Blue
Owner: Jacqui Maher
Height: 6'2"
Weight: 130 lbs

Ответы [ 4 ]

0 голосов
/ 11 января 2019

Вы можете легко получить это, используя Perl

$ perl -0777 -ne ' @a=split("--"); @b=grep { /L337/ and /Honda/ and /Blue/ and /Height: 6/ } @a; print @b ' jules.txt
License Plate L337QE9
Make: Honda
Color: Blue
Owner: Erika Owens
Height: 6'5"
Weight: 220 lbs
$ cat jules.txt  # your file 
License Plate L337QE9
Make: Honda
Color: Blue
Owner: Erika Owens
Height: 6'5"
Weight: 220 lbs
--
--
License Plate L337GB9
Make: Toyota
Color: Blue
Owner: Matt Waite
Height: 6'1"
Weight: 190 lbs
--
--
License Plate L337OI9
Make: Jaguar
Color: Blue
Owner: Brian Boyer
Height: 6'6"
Weight: 201 lbs
--
--
$
0 голосов
/ 09 января 2019

С GNU awk вы можете делать следующее:

awk 'BEGIN{RS="\n--\n?";ORS="\n--\n"; FS="\n"}
     ($1 ~ /L337/) && ($2 ~ /Honda/) && ($3 ~ /Blue/) && ($5 ~ /[^0-9]6'/)' file

Это поднимет все Blue Honda с номерным знаком, начиная с L337, и высотой от 6 до 7 футов.

Если поля не всегда в одном и том же порядке, вам придется немного им манипулировать.

awk '/License Plate/ && /L337/ { f++ }
     /Make/ && /Honda/ { f++ }
     /Color/ && /Blue/ { f++ }
     /Height/ && / 6'2/ { f++ }
     { record = record=="" ? $0 : record ORS $0 }
     /^--$/ { if (f == 4) print record; f=record=""}
     END { if (f==4) print record; }
0 голосов
/ 09 января 2019

Я плохо сформулировал этот вопрос, но с другой стороны, @kvantour побудил меня найти решение.

Имеется 3 таких данных:

License Plate L337QE9
Make: Honda
Color: Blue
Owner: Erika Owens
Height: 6'5"
Weight: 220 lbs
--
--
License Plate L337GB9
Make: Toyota
Color: Blue
Owner: Matt Waite
Height: 6'1"
Weight: 190 lbs
--
--
License Plate L337OI9
Make: Jaguar
Color: Blue
Owner: Brian Boyer
Height: 6'6"
Weight: 201 lbs
--

Я хочу сопоставить табличку с 'L337', то есть Blue, Honda, с владельцем, которому не менее 6 '. Или я хочу удалить любые результаты, которые не соответствуют всем этим требованиям. Я не ожидаю каких-либо результатов с красными автомобилями, Toyota или короткими владельцами, поэтому будет возвращена только запись Эрики Оуэнс.

Мое рабочее решение выглядит следующим образом:

grep -A5 'L337' ./vehicles | grep -B1 -A4 'Honda'  | grep -B2 -A3 'Blue' | grep -B4 -A1 'Height: 6'

Открытие -Bn позволило мне фильтровать без потери верхних строк. Спасибо всем за вклад и приносим извинения за путаницу.

0 голосов
/ 09 января 2019

Если я правильно понял, вы НЕ хотите печатать раздел, который имеет любой другой цвет, кроме синего (можно изменить имя цвета в условии, если не синий), тогда может помочь следующее.

awk '
/License Plate/ && value{
  if(flag==1){
    print value
  }
  flag=value=""
}
/Color:/ && $2=="Blue"{
  flag=1
}
{
  value=(value?value ORS $0:$0)
}
END{
  if(flag==1){
    print value
  }
}'   Input_file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...