Excluir caracteres de nova linha entre padrões

0
foo
I love
Stack Exchange
bar
Some junk
lines
foo
Welcome to the
world of
Bash
bar
foo
Elon Musk
rocks

Sim, não há bar complementando foo no final do arquivo

A saída exigida é

I love Stack Exchange
Welcome to the world of Bash
Elon Musk rocks

Portanto, remova todos os caracteres de nova linha entre ^foo e ^bar ou entre ^foo e end of file , quando não houver bar

    
por GypsyCosmonaut 17.09.2018 / 02:17

3 respostas

2

com awk :

awk '
  $0 == "foo" {if (sep) print ""; sep = ""; inside = 1; next}
  $0 == "bar" {inside = 0; next}
  inside {printf "%s", sep $0; sep = " "}
  END {if (sep) print ""}'

Para corresponder às linhas com foo como a primeira palavra, substitua $0 == "foo" por $1 == "foo" ; para combinar nas linhas que começam com foo , substitua por /^foo/ (abreviação de $0 ~ /^foo/ ).

    
por 17.09.2018 / 09:00
2

Perl para o resgate!

perl -ne '
    if ($e = /^foo$/ .. /^bar$/) {
        if ($e =~ /E/) { print "\n" }
        else {
            chomp;
            print " " if $e > 2;
            print     if $e > 1;
        }
}' -- input.txt
  • -n lê a linha de entrada por linha
  • .. é o operador range, ele retorna o número da linha relativa de cada linha em um bloco. A última linha tem E0 anexada a ela.
por 17.09.2018 / 02:43
2

Você também pode fazer isso:

a) Este é o código POSIX-sed compatível, no qual armazenamos as linhas intermediárias (! / foo / e! / bar /) na área de espera.

sed -e '
    /foo/,/bar/!d
    /foo/d
    /bar/!{H;$!d;}
    s/.*//;x;s/^\n//;y/\n/ /
' input-file.txt

b) e com Perl como mostrado

perl -lne '
   next unless /foo/ ... /bar/;
   push(@A, $_),next if !/foo/ && !/bar/ && !eof;
   push(@A, $_)      if !/foo/ && !/bar/ &&  eof;
   print join " ", splice @A if /bar/ || !/foo/ && eof;
' input-file.txt

Explicação:

  • pule linhas ou linhas não interessantes que estão fora do intervalo. Um intervalo é definido como começando com uma linha contendo /foo/ e terminando com /bar/ , ambos ocorrendo em linhas separadas.
  • Quando estivermos no intervalo, executemos ações separadas com base na linha em que estamos.
  • Para linhas que não são / foo /, nem / bar / e nem eof: armazenam a linha na matriz @A . Depois de armazenar, volte para ler o próximo registro, desde que não exista.
  • Apenas para o fim do intervalo, ou seja, /bar/ ou eof , tomamos a ação de imprimir o que está em @A e também o esvaziamos, em preparação para o próximo ciclo de coleta.
por 17.09.2018 / 10:26