Imagine uma saída de um comando como
44444
55555
11111
22222
33333
como posso arrancar as primeiras N linhas (as duas primeiras no exemplo acima) e anexá-las no final, mas sem usar o arquivo temporário (usando apenas tubos)?
11111
22222
33333
44444
55555
Algo do tipo | sed -n '3,5p;1,2p'
(que obviamente não funciona como sed não se importa com a ordem dos comandos).
command-line
text-processing
Peter Uhnak
fonte
fonte
Respostas:
Apenas copie essas linhas para o buffer de espera (exclua-as) e, quando estiver na última linha, adicione o conteúdo do buffer de espera ao espaço do padrão:
Com
gnu sed
você poderia escrever comoAqui está outra maneira com o ol '
ed
(eler
direciona a saídasome command
para o buffer de texto e, em seguida,m
fornece linhas1,NUMBER
após o último$
):Observe que, conforme indicado, ambos falharão se a saída tiver menos de
NUMBER
+1 linhas. Uma abordagem mais sólida seria (gnu sed
sintaxe):este exclui apenas as linhas desse intervalo, desde que não sejam a última linha (
$!d
); caso contrário, substitui o espaço do padrão pelo conteúdo do buffer de retenção (g
) e, em seguida,q
uits (após a impressão do espaço do padrão atual).fonte
sed -e '1,NUMBER{H;1h;d;}' -e '$G'
também funciona portably (note que algumassed
implementações não pode deter mais do que alguns kilobytes no espaço de espera, de modo NÚMERO não pode ser muito grande lá)sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'
?-e
substitui uma nova linha.d;}
ainda não é POSIX, mas portátil. Isso será corrigido na próxima especificação do POSIX. Veja austingroupbugs.net/view.php?id=944#c27201,NUMBER{H;1h;d;}
não é ter ponto e vírgula imediatamente após a chave de abertura . Isso pode ter sido apenas um bug no SunOS 4.1,sed
cuja solução alternativa ainda está conectada aos meus dedos 20 anos depois.Uma
awk
abordagem:Um benefício sobre a
sed
abordagem de @ don_crissti é que ele ainda funciona (gera as linhas) se a saída tivern
linhas ou menos.fonte
\n
pelo ORS, para que isso funcione com outros separadores de registros (digamos que você queira usar parágrafos, etc.).Eu tenho
xclip
e com isso isso pode ser feito desta maneira:Aqui está sua descrição:
fonte
Uma maneira Perl:
Ou, a mesma coisa escrita de forma menos enigmática:
Por exemplo:
Explicação
-ne
: leia o arquivo de entrada / fluxo linha por linha e aplique o script fornecido por-e
cada linha.$.<3
:$.
é o número da linha atual; portanto, mude3
para o número de linhas que você deseja alterar.$.<3?($f.=$_):print;
: este é o operador condicional, o formato geral écondition ? case1 : case2
, ele será executadocase1
secondition
for verdadeiro ecase2
se for falso. Aqui, se o número da linha atual for menor que 3, ele anexará a linha atual ($_
) à variável$f
e, se o número da linha for maior que 3, será impresso.}{ print $f
: o}{
é perl abreviação paraEND{}
. Ele será executado após todas as linhas de entrada terem sido processadas. Nesse ponto, teremos coletado todas as linhas que queremos mudar e impressas todas as que queremos deixar em paz; portanto, imprima as linhas salvas como$f
.fonte
perl -ne '$.<3?$f.=$_:print}{print $f
Use POSIX
ex
. Sim, ele se destina à edição de arquivos, mas funcionará em um pipeline.Isso pode ter quaisquer comandos arbitrários adicionados no início ou no final do pipeline e funcionará da mesma maneira. Melhor ainda, dada a presença de
/dev/stdin
, é compatível com POSIX.(Não sei se
/dev/stdin
está especificado no POSIX ou não, mas vejo que está presente no Linux e no Mac OS X.)Isso tem uma vantagem de legibilidade em relação ao uso
sed
do espaço de espera - basta dizerex
"mova essas linhas para o fim" e o faz. (O restante dos comandos significa "imprimir o buffer" e "sair", que também são legíveis.)NB: O
ex
comando fornecido acima falhará se for fornecido menos de 2 linhas como entrada.Leitura adicional:
fonte
Um pequeno
python
trecho:Passe o nome do arquivo como primeiro argumento e o número de linhas para mover como segundo argumento.
Exemplo:
fonte
Se você pode armazenar toda a saída na memória:
fonte
Aqui está outra opção que requer o GNU
sed
:-u
torna o GNUsed
sem buffer, para que osed
comando não consuma mais de 3 linhas de STDIN. A substituição do comando remove as linhas vazias, para que o comando não inclua linhas vazias no final da saída, se a terceira, terceira e segunda ou terceira, segunda e primeira linhas estiverem vazias.Você também pode fazer algo assim:
Sem
sponge /dev/stdout|
o comando falharia com entradas longas.sponge /dev/stdout
também pode ser substituído portac|tac
, mesmo que seja impressa, por exemplo,a\ncb
se a entrada éa\nb\nc
onde\n
está um avanço de linha, ou com(x=$(cat);printf %s\\n "$x")
, mesmo que isso remova linhas vazias do final da entrada. O comando acima exclui a primeira linha quando o número de linhas da entrada é uma ou duas.fonte