Como usar o sed para encontrar as cordas entre dois padrões?

Eu tenho conteúdo de arquivo como este:

aaa accounting exec ... aaa accounting exec ... aaa accounting commands .. aaa accounting commands .. aaa accounting commands .. aaa accounting commands .. aaa accounting commands .. aaa accounting commands .. aaa accounting network .. aaa accounting connection .. aaa accounting system .. ! aaa accounting exec default action-type start-only group tacacs+ ! aaa accounting exec default stop-only group tacacs+ 

A saída deve ser assim:

 aaa accounting exec default .. aaa accounting exec default action-type start-only group tacacs+ ! aaa accounting exec default .. 

Eu tentei seguir o comando sed :

 sed -n '/aaa accounting exec default/,/!/p' AboveFileContent.txt 

Mas não é produzir o que eu quero.

Qual seria a solução? Eu tentei usar o awk também, mas o mesmo resultado está chegando. Qual seria o comando para obter o resultado exato?

Eu usaria o awk para isso:

 awk ' /aaa accounting exec default/ {print; exec=1; next} exec { if (/^ /) {print; next} else if (/^!/) {print} exec=0 } ' filename 

Passando o padrão, use a opção -v do awk e, em seguida, o operador de correspondência de padrões ~ :

 awk -v patt='aaa accounting exec default' ' $0 ~ patt {print; exec=1; next} exec { if (/^ /) {print; next} else if (/^!/) {print} exec=0 } ' filename 

Você está tentando obter dados estruturados no formulário:

 aaa ... ... ... ! 

Você precisa tornar o sed ciente de que os blocos recuados são importantes. Uma maneira crua pode ser escrever um loop no sed :

 sed -n ' # Create a label named 'start' :start # If the line matches the beginning of a block, # jump (branch) to the label named section /aaa accounting exec default/ b section # If we didn't branch, get the next line n # Jump back to the start label b start # The label named section :section # print the line p n # Keep looping to section for the lines we need /^ /,/!/ b section # If we don't have any more lines to loop on, # jump back to the beginning b start ' 

Em uma linha:

 $ sed -n ':start; /aaa accounting exec default/ b section; n; b start; :section; p; n; /^ /, /!/ b section; b start' test.txt aaa accounting exec default start-stop group tacacs+ aaa accounting exec default action-type start-only group tacacs+ ! aaa accounting exec default stop-only group tacacs+ 

Isso poderia ser feito de uma maneira mais legível usando awk , perl ou python , eu acho.