Executar operações sed em determinados números de linha

8

Gostaria de saber se existe uma maneira simples de operar em determinadas linhas com números de linhas pré-atribuídos.

Digamos que eu queira produzir as 1ª, 7ª, 14ª e 16ª linhas de um arquivo, posso simplesmente fazer

sed -n '1p;7p;14p;16p' input_file

mas isso fica mais complicado quando a operação não está apenas imprimindo e eu não quero escrever o mesmo comando longo 4 vezes (e sim, eu sei que posso construir esse comando sed longo substituindo a mesma variável bash 4 vezes, mas isso não é ideal o suficiente ...), ou seja

sed -n '1{long_command};7{long_command};14{long_command};16{long_command}' input_file

Existe uma maneira de fazer a operação nessas linhas específicas do meu arquivo? Eu estou esperando algo como,

sed -n '1,7,14,16p'

o que certamente não funcionará na forma atual.

Qualquer ajuda será apreciada. "Não, não é possível." com explicações também é uma resposta que vou aceitar.

Weijun Zhou
fonte
é fácil comawk
RomanPerekhrest 15/01

Respostas:

11

Você pode usar ramos:

sed '
  1b1
  7b1
  14b1
  16b1

  # for the rest to be left alone, branch off (or delete them with "d"):
  b

  :1
  long_command'

(observe que você também pode adicionar alguns 20,25b1intervalos /re/b1de linhas ou incluir linhas que correspondam ao re).

Ou você pode usar awk:

awk 'NR == 1 || NR == 7 || ... {stuff}'

Ou usando um hash:

awk -v l=1,7,14,16 '
  BEGIN{split(l, a, ","); for (i in a) lines[a[i]]}

  NR in lines {stuff}'

(ou BEGIN{lines[1]lines[7]lines[14]lines[16]}se não houver muitos)

Stéphane Chazelas
fonte
Obrigado, nunca pensei em ramificações ... Apenas parece ser a ferramenta ideal para usar neste caso.
Weijun Zhou
como usar ramos como este no sed com um padrão de pesquisa? como dizer que eu quero combinar ou excluir um padrão após a enésima linha?
Qodeninja
3

Simplesmente inverta sua seleção e exclua-a:

sed '2,6d;8,13d;15d;17,$d;long_command'
Philippos
fonte
Essa também é uma solução interessante, embora um pouco mais difícil para lidar com números de linhas lidos no stdin, por exemplo.
Weijun Zhou
1

Primeira variante:

Você pode usar este truque:

sed -nf <(printf '%dp\n' 1 7 14 16)

-f script-file - adiciona o conteúdo do arquivo de script aos comandos a serem executados.

Teste

seq 1 20 | sed -nf <(printf '%dp\n' 1 7 14 16)

Resultado

1
7
14
16

Segunda variante:

No início, o auxiliar sedé usado para filtrar apenas as linhas necessárias do arquivo, depois essas linhas são direcionadas para a principal sedcom o comando long.

sed -n '1p; 7p; 14p; 16p' input.txt | sed 'long command'
MiniMax
fonte