Dividir arquivo e invocar comandos passando cada uma das partes via stdin sem arquivos temporários

1

Arquivo de exemplo:

abc
def
%separator
eee
fff
%separator
xxx
yyy
zzz

É possível dividir este arquivo nas partes lógicas, por exemplo:

parte 1:

abc
def

parte 2:

eee
fff

parte 3:

xxx
yyy
zzz

invoque algum comando (digamos wc -l ) em cada uma dessas partes sem criar arquivos temporários? O que eu estou procurando é algo como xargs que não irá inline argumentos, mas empurrá-los através stdin vez.

    
por levant pied 16.08.2017 / 19:55

1 resposta

1

Eu não conheço essa ferramenta. Eu vim com o seguinte script. Ajuste-o às suas necessidades:

#!/bin/bash

sprtr='%separator'
cmmnd='wc -l'

set -o pipefail

while ! sed -n "/^${sprtr}$/q1;p" | $cmmnd ; do
 :
done

É assim:

  1. sed lê de stdin até encontrar um determinado separador ou EOF e, em seguida, sai.
  2. O comando escolhido recebe o fragmento apropriado de sed .
  3. A menos que $cmmnd falhe, set -o pipefail , ! e q1 colabore, portanto, quando $sprtr for encontrado, o canal inteiro retornará o status de saída 0 . Isso executa o código (vazio) entre do e done e, em seguida, faz um loop, então sed é executado novamente para servir o próximo fragmento.
  4. Se $cmmnd falhar ou se $sprtr não for encontrado (EOF alcançado), todo o canal retornará status de saída diferente de zero. Isso faz com que o script deixe o loop while .

Algumas armadilhas:

  • Você não pode usar nenhum separador literalmente e sem pensar. Alguns valores de $sprtr irão quebrar o comando sed ou alterar seu comportamento se você não escapar de caracteres especiais à sua sintaxe. Exemplos: / , /q; / .
  • set -o pipefail funciona no Bash 3 e acima, eu acho. A alternativa (mas não equivalente) é mispipe de moreutils .
  • Seu sed precisa entender q1 (isso sai sed com o código de saída 1 ).

Eu admito que não há muita elegância nesta solução.

    
por 28.08.2017 / 21:21

Tags