У меня есть файл, который выглядит так:
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, но пока не нашел решения. Есть идеи?
Спасибо!
Что вы пробовали? Какое это имеет отношение к bash
? Где вы нашли, что bash
обеспечивает pcregrep
? Опубликуйте свои попытки, сделанные до сих пор
Почему в выводе есть пробелы между двумя строками?
@ПС. Я отредактировал свой оригинальный пост. Я упустил некоторую информацию раньше. Вы правы в том, что предложенное вами регулярное выражение решает то, что я изначально написал, поэтому я проголосовал.
@Inian Я обновил свой исходный пост, я упустил некоторую информацию. Что касается bash, я пишу команды pcregrep в оболочке bash на OS X (терминал). Примером того, что я пробовал до сих пор, является pcregrep -M '^a(?=(^b))^c' , где я пытаюсь сопоставить строку, начинающуюся с "a", которая имеет "b" строку перед ней и строку «c», а также включить только строки «a» и «c».
Вы, вероятно, хотите awk-решение, многострочное с grep быстро становится грязным.
Пытаться:
$ 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 -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 раньше, но я попробую использовать это.
зачем усложнять
pcre
, вы пробовалиgrep -E '^[ac]'
?