Bash: как определенные строки, но исключить определенные строки между ними?

У меня есть файл, который выглядит так:

a: 0
a: 0
a: 0
a: 1
b: 1
c: 1
d: 1
e: 1
f: 1
a: 2
b: 2
c: 2
d: 2
e: 2
f: 2
a: 3
b: 3
c: 3
d: 3
e: 3
f: 3
c: 4
c: 4
c: 4

Я хочу захватить и вывести все строки a и c формы <a line><anything other than an a or c line><c line>, чтобы вывод выглядел так:

a: 1
c: 1

a: 2
c: 2

a: 3
c: 3

Обратите внимание, что ни строки a: 0 в начале, ни строки c: 4 в конце не захватываются, потому что они не следуют шаблону, который я упомянул. Также обратите внимание, что строки b между строками a и c удалены.

Я пытался сделать это с помощью поиска, используя pcregrep Bash, но пока не нашел решения. Есть идеи?

Спасибо!

зачем усложнять pcre , вы пробовали grep -E '^[ac]' ?

P.... 30.05.2019 20:53

Что вы пробовали? Какое это имеет отношение к bash? Где вы нашли, что bash обеспечивает pcregrep? Опубликуйте свои попытки, сделанные до сих пор

Inian 30.05.2019 20:54

Почему в выводе есть пробелы между двумя строками?

Benjamin W. 30.05.2019 20:56

@ПС. Я отредактировал свой оригинальный пост. Я упустил некоторую информацию раньше. Вы правы в том, что предложенное вами регулярное выражение решает то, что я изначально написал, поэтому я проголосовал.

gkeenley 30.05.2019 21:02

@Inian Я обновил свой исходный пост, я упустил некоторую информацию. Что касается bash, я пишу команды pcregrep в оболочке bash на OS X (терминал). Примером того, что я пробовал до сих пор, является pcregrep -M '^a(?=(^b))^c' , где я пытаюсь сопоставить строку, начинающуюся с "a", которая имеет "b" строку перед ней и строку «c», а также включить только строки «a» и «c».

gkeenley 30.05.2019 21:08

Вы, вероятно, хотите awk-решение, многострочное с grep быстро становится грязным.

Benjamin W. 30.05.2019 21:12
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
447
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Использование awk

Пытаться:

$ awk -F: '$1= = "a"{aline=$0} $1= = "c"{if (aline)print aline ORS $0 ORS; aline = ""}' file
a: 1
c: 1

a: 2
c: 2

a: 3
c: 3

Как это работает

По умолчанию awk читает по одной строке за раз.

  • -F:

    Это говорит awk использовать : в качестве разделителя полей.

  • $1= = "a"{aline=$0}

    Каждый раз, когда наблюдается строка a, сохраняйте строку в переменной aline.

  • $1= = "c"{if (aline)print aline ORS $0 ORS; aline = ""}

    Каждый раз, когда наблюдается строка c, проверяем, есть ли у нас непустая aline. Если это так, выведите aline и текущую строку, разделенные символами новой строки. Кроме того, установите aline обратно на пустую строку.

Многострочная версия

Для тех, кто предпочитает, чтобы их команды распределялись по нескольким строкам:

awk -F: '
    $1= = "a"{
        aline=$0
    }

   $1= = "c"{
        if (aline)
            print aline ORS $0 ORS
        aline = ""
    }' file

Использование sed

$ sed -n '/^a/h; /^c/{x;/^a/{p;x;s/$/\n/;p};h}' file
a: 1
c: 1

a: 2
c: 2

a: 3
c: 3

Как это работает

  • -n

    Это говорит sed ничего не печатать, если мы явно не попросим его об этом.

  • /^a/h

    Всякий раз, когда у нас есть строка, начинающаяся с a, мы сохраняем ее в место для хранения.

  • /^c/{ x; /^a/{ p; x; s/$/\n/; p}; h}

    Каждый раз, когда у нас есть строка, начинающаяся с c, мы:

    • Мы меняем (x) пространство шаблона с пространством удержания.

    • Если новое пространство шаблонов начинается с a, то мы печатаем (p) его и снова меняем местами (x), добавляем новую строку в конец нового пространства шаблонов (s/$/\n/) и печатаем (p) его.

    • Наконец, мы сохраняем текущее пространство шаблона (которое начинается с c) в пространство для хранения.

Спасибо! Я не использовал awk раньше, но я попробую использовать это.

gkeenley 30.05.2019 22:29

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