1

У меня есть несколько текстовых файлов с этим форматом:

name: john
address: bay area
phone: 6505561234
image: /work/myimage.png

name: stark
dob: 5AD
shirt color: red
physical address: Westros
phone model: S2
email id: me@stark.org

phone model: S2
name: tara
dob: 1ad
shirt color: red
physical address: Westros
email id: me@stark.org

Там может быть несколько человек или контакт. Допустим, я хочу найти всех людей с моделью телефона «S2».

Я могу сделать 'grep' - это просто вернет это:

phone model: S2
phone model: S2

Я могу использовать контекст до / после в grep - но это просто фиксированное количество строк до / после того, как они будут распечатаны. С «предыдущим» контекстом 3 я мог бы получить что-то вроде этого:

shirt color: red
physical address: Westros
phone model: S2
---
name: tara
dob: 1ad
phone model: S2

Но это не то, что я хочу. Я хочу, чтобы появилась вся «запись». Любые подсказки о том, как сделать это с помощью стандартных команд Unix?

5 ответов5

4

awk 'BEGIN {RS="\n\n"} $0 ~ /PATTERN/ {print $0"\n---"}' record

Просто замените PATTERN на то, что вы хотите.

1

Если вы замените пустые строки на --- , ваш документ будет действительным файлом YAML. Это хорошо представляет структуру записи, как у вас.

perl -p -e 's/^$/---/g' input > test.yml

Затем, чтобы получить полные записи:

ruby -e 'require "yaml"; 
YAML::load_documents(File.open("test.yml")) do |d| 
  puts d.to_yaml if d["phone model"] == "S2" rescue nil
end'

Это печатает:

---
name: stark
dob: 5AD
shirt color: red
physical address: Westros
phone model: S2
email id: me@stark.org
---
name: tara
dob: 1ad
phone model: S2
shirt color: red
physical address: Westros
email id: me@stark.org

Отмечен как CW, так как вы запрашивали стандартные инструменты Unix, чего, очевидно, нет в ruby . Работает с Ruby 1.8.7, 1.9.3 и 2.0.0.

0

Решение с awk довольно опрятное. Вот возможное решение с помощью sed:

  1. -n ничего не печатать
  2. все непустые строки добавляются в регистр удержания
  3. когда встречается пустая строка, регистр удержания и пространство шаблона меняются местами
    • если пространство шаблона содержит строку, переданную в качестве первого аргумента функции look4pattern(), печатается весь набор строк.
  4. так же, как 3. для последней строки (не могу знать, пуста ли последняя строка)

$ look4pattern() { 
    sed -n '
    /^$/!{H}; 
    /^$/{ x ; /'$1'/p }; 
       ${ x ; /'$1'/p }
  ' < records.txt
  }

$ look4pattern S2

name: stark
dob: 5AD
shirt color: red
physical address: Westros
phone model: S2
email id: me@stark.org

name: tara
dob: 1ad
phone model: S2
shirt color: red
physical address: Westros
email id: me@stark.org
0

Записи, разделенные пустыми строками, на самом деле являются общим форматом для файлов удачи, и (по крайней мере, в той версии, которая у меня есть, fortune-mod для Arch Linux), есть опция -m которая печатает все состояния (записи), соответствующие регулярному выражению. Так что-то вроде этого:

fortune -m "model: S2"

и он напечатает все ваши записи.

0

Используя этот вопрос мне удается найти способ сделать многострочный grep для блоков:

grep -Pzo 'name:(..*\n)*phone model:.*S2.*(..*\n)*' filename \
 | sed 's/^name:/---\nname:/' \
 | tail -n +2

где (..*\n)* - любое количество заразных непустых строк. -P включает синтаксис perl, -z разрешает поиск новой строки и -o печатает только совпадения. Sed используется для разделения и режет хвоста первой линии.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .