Как распечатать определенный раздел из файла, если в этом разделе есть ключевое слово для поиска [BASH]

Ниже приведен фрагмент файла с именем "books.info":

TITLE and AUTHOR                                                     ETEXT NO.

Aspects of plant life; with special reference to the British flora,      56900
 by Robert Lloyd Praeger

The Vicar of Morwenstow, by Sabine Baring-Gould                          56899
 [Subtitle: Being a Life of Robert Stephen Hawker, M.A.]

Raamatun tutkisteluja IV, mennessä Charles T. Russell                    56898
 [Subtitle: Harmagedonin taistelu]
 [Language: Finnish]

Tom Thatcher's Fortune, by Horatio Alger, Jr.                            56896

A Yankee Flier in the Far East, by Al Avery                              56895
 and George Rutherford Montgomery
 [Illustrator: Paul Laune]

Nancy Brandon's Mystery, by Lillian Garis                                56894

The Junior Classics, Volume 3: Tales from Greece and Rome, by Various    56887


~ ~ ~ ~ Posting Dates for the below eBooks:  1 Mar 2018 to 31 Mar 2018 ~ ~ ~ ~

TITLE and AUTHOR                                                     ETEXT NO.

The American Missionary, Volume 41, No. 1, January, 1887, by Various     56886

Morganin miljoonat, mennessä Sven Elvestad                               56885
 [Author a.k.a. Stein Riverton]
 [Subtitle: Salapoliisiromaani]
 [Language: Finnish]

"Trip to the Sunny South" in March, 1885, by L. S. D                     56884

Balaam and His Master, by Joel Chandler Harris                           56883
 [Subtitle: and Other Sketches and Stories]

Я пытаюсь получить полную информацию о книге, если ищу ее по имени автора.

Пример1:

Ключевое слово для поиска: Аль Эйвери

Тогда возврат должен быть:

A Yankee Flier in the Far East, by Al Avery                              56895
 and George Rutherford Montgomery
 [Illustrator: Paul Laune]

Пример 2:

Ключевое слово для поиска: Роберт Ллойд Прегер

Тогда возврат должен быть:

Aspects of plant life; with special reference to the British flora,      56900
 by Robert Lloyd Praeger

Я пробовал это:

#!/bin/bash
if [ -f books.info ]
then
    echo Please enter search keyword:
    read keyword
    command=$(grep -i "$keyword" books.info)
    echo $command
else
    echo books.info file is missing
fi

Но это работает не так, как я хочу. Может ли кто-нибудь помочь мне с этим?


РЕДАКТИРОВАТЬ

Обновил структуру файла после того, как заметил строку даты. Пытался: awk -v RS = '\ n \ n' "/ $ {keyword} /" infile а также: awk -v RS = -v keyword = "$ keyword" '$ 0 ~ keyword' file.txt Как следует из ответов, приведенных ниже @andlrc и @ αғsнιη, но он распечатывает много других материалов, которые не связаны. Я предполагаю, что эта строка нарушает его:

~ ~ ~ ~ Posting Dates for the below eBooks:  1 Mar 2018 to 31 Mar 2018 ~ ~ ~ ~

Поскольку в верхней части этой строки есть 2 пробела, а под одним пробелом, я думаю, из-за двух верхних пробелов он не работает должным образом.

Предлагаю взглянуть на sed.

Cyrus 01.05.2018 12:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
46
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать команду grep, как показано ниже: -

 grep search_string -A n -B m file.extension

Здесь -A обозначает строку после поиска, а -B обозначает строку до строки поиска, поэтому, вероятно, вы можете попробовать: -

command=$(grep -i -A 2 "$keyword" books.info)  

это верно для "Example1", а что насчет Example2?

αғsнιη 01.05.2018 13:04
Ответ принят как подходящий

Я бы использовал awk, просто определите пустую строку как рecord Separator и найдите строку, содержащуюся в любом блоке:

awk -v RS='\n\n' '/Al Avery/' infile 

или установите RS в пустую строку

awk '/Al Avery/' RS= infile

Если вам нужно получить блок для каждого ввода пользователя, вы можете сделать:

awk -v RS='\n\n' "/${keyword}/" infile

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


для работы с ключевое слово, если он содержал обратную косую черту \ или косую черту / и любые другие, вы можете использовать awk следующим образом (для Shell (Bash, ksh, ksh93, mksh, zsh) which supports Pattern Substitution Expansion):

PATTERN = "${keyword//\/\\\\}" awk '$0 ~ ENVIRON["PATTERN"]' RS= infile

Можно установить RS в ноль с тем же результатом: awk -v RS= '/Al avery/' infile См. man awk | awk '/RS is null/' RS=

andlrc 01.05.2018 13:06

Что произойдет, если переменная "ключевое слово" будет содержать косую черту (/)?

andlrc 01.05.2018 13:14
Голосующий вниз: не молчите, не стесняйтесь объяснять свой голос против, пожалуйста.
αғsнιη 02.05.2018 04:17

Вы можете использовать awk и переменную разделителя записей:

awk -v RS= -v keyword = "$keyword" '$0 ~ keyword' file.txt

Вы можете установить переменные для awk с помощью опции -v; -v name=val. В вашем случае нам нужно установить переменную keyword в значение одноименной переменной bash:

-v keyword = "$keyword"

Скрипт awk:

$0 ~ keyword

который будет сопоставлять весь блок содержимого с регулярным выражением, указанным в переменной "keyword".

If RS is null, then records are separated by sequences consisting of a plus one or more blank lines

Источник: $ man awk | awk '/RS is null/' RS=

Нет необходимости передавать ключевое слово в качестве переменной awk, мы можем использовать двойные кавычки вместо одинарных кавычек для awk, тогда оболочка выполнит расширение переменной, см. Мой ответ выше.

αғsнιη 01.05.2018 13:15

@ αғsнιη Не получится, если "ключевое слово" содержит косую черту.

andlrc 01.05.2018 13:18

Правильно, а что если в вашем не было обратных косых черт "\" :)

αғsнιη 01.05.2018 13:31

Другие вопросы по теме