Как я могу напечатать только строки, которым сразу предшествует пустая строка в файле, используя sed? - PullRequest
1 голос
/ 05 апреля 2019

У меня есть текстовый файл со следующей структурой:

bla1
bla2

bla3
bla4

bla5

Итак, вы можете видеть, что некоторым строкам текста предшествует пустая строка.

Я понимаю, что sed имеетконцепция двух буферов, буфера пространства шаблонов и буфера пространства удержания, так что я предполагаю, что они должны войти, чтобы играть здесь, но я не знаю, как их указать для достижения того, что мне нужно.

В моем надуманном примере выше я ожидал увидеть следующие строки:

bla3
bla5

Ответы [ 6 ]

2 голосов
/ 05 апреля 2019

sed для s / old / new в отдельных строках, вот и все.Каждый раз, когда вы начинаете говорить о буферах или делать что-либо, связанное с многострочным сравнением, вы используете неправильный инструмент.

Вы можете сделать это с помощью awk:

$ awk -v RS= -F'\n' 'NR>1{print $1}' file
bla3
bla5

, но это не получитсянапечатать первую непустую строку, если первые строки в файле были пустыми, поэтому это может быть тем, что вам нужно, если вы хотите, чтобы строки всех пробелов считались пустыми:

$ awk 'NF && !p{print} {p=NF}' file
bla3
bla5

и это иначе:

$ awk '($0!="") && (p==""){print} {p=$0}' file
bla3
bla5

Все вышеперечисленное будет работать, даже если перед любой данной непустой строкой будет несколько пустых строк.

Чтобы увидеть разницу между тремя подходами (которыеВы не увидите, учитывая образец ввода в вопросе):

PS1> printf '\nfoo\n      \nbar\n\netc\n' | cat -E
$
foo$
      $
bar$
$
etc$

PS1> printf '\nfoo\n      \nbar\n\netc\n' | awk -v RS= -F'\n' 'NR>1{print $1}'
etc

PS1> printf '\nfoo\n      \nbar\n\netc\n' | awk 'NF && !p{print} {p=NF}'
foo
bar
etc

PS1> printf '\nfoo\n      \nbar\n\netc\n' | awk '($0!="") && (p==""){print} {p=$0}'
foo
etc
1 голос
/ 05 апреля 2019
awk 'p;{p=/^$/}' file
Команда

выше делает это для каждой строки:

  1. , если p равно 1, строка печати;
  2. , если строка пуста, установить p в 1.

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

awk 'p;{p=!NF}' file

для печати непустых строк, каждая из которых идет сразу после пустой строки, вы можете использовать это:

awk 'p*!(p=/^$/)' file
  1. если p равно 1 и эта строка не пуста (1*!(0) = 1*1 = 1), выведите эту строку;
  2. В противном случае (1*!(1) = 1*0 = 0, 0*anything = 0) ничего не печатать.

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

awk 'p*(/./);{p=/^$/}' file

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

awk 'p*NF;{p=!NF}' file

смотрите их онлайн здесь и здесь .

1 голос
/ 05 апреля 2019

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

sed -n -e '/^$/{x; p;}' -e h input

Но я не вижу простого способа использовать его для вашего случая использования. Для вашего случая вместо использования буфера удержания вы можете выполнить:

sed -n -e '/^$/ba' -e d -e :a -e n -e p input

Но я бы сделал это с awk.

awk 'NR!=1{print $1}' RS= FS=\\n input-file
0 голосов
/ 05 апреля 2019

проверено gnu sed, ваши данные в 'a':

$ sed -nE '/^$/{N;s/\n(.+)/\1/p}' a
bla3
bla5

опция -i добавляется перед реальным редактированием -n

0 голосов
/ 05 апреля 2019

Вы можете использовать sed, чтобы сопоставить диапазон строк и выполнить под-совпадения внутри совпадений, например:

# - use the "-n" option to omit printing of lines
# - match lines between a blank line (/^$/) and a non-blank one (/^./),
#   then print only the line that contains at least a character,
#   i.e, the non-blank line.
sed -ne '
/^$/,/^./ {
    /^./{ p; }
}' input.txt
0 голосов
/ 05 апреля 2019

Если sed / awk не обязателен, вы можете сделать это с помощью grep:

grep -A 1 '^$' input.txt  | grep -v -E '^$|--'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...