Eu tenho um despejo de SQL ~ 23000 linhas contendo vários bancos de dados no valor de dados. Eu preciso extrair uma certa seção deste arquivo (ou seja, os dados para um único banco de dados) e colocá-lo em um novo arquivo. Conheço os números das linhas inicial e final dos dados que desejo.
Alguém conhece um comando Unix (ou série de comandos) para extrair todas as linhas de um arquivo entre as linhas 16224 e 16482 e, em seguida, redirecioná-las para um novo arquivo?
unix
command-line
sed
text-processing
Adam J. Forster
fonte
fonte
Respostas:
No manual sed :
e
fonte
sed -n '16224,16482p;16483q' filename
. Caso contrário, o sed continuará digitalizando até o fim (ou pelo menos minha versão).Onde 16224,16482 são o número da linha inicial e o número da linha final, inclusive. Isso é indexado em 1.
-n
suprime o eco da entrada como saída, o que você claramente não deseja; os números indicam o intervalo de linhas para que o seguinte comando opere; o comandop
imprime as linhas relevantes.fonte
sed -n '16224,16482p;16482q' orig-data-file > new-file
.Muito simples usando cabeça / cauda:
usando sed:
usando awk:
fonte
tail
.sed -n 16224,16482p' in.sql >out.sql
eo comando awk deve serawk 'NR>=16224&&NR<=16482' in.sql > out.sql
head -16482 in.sql | tail -$((16482-16224)) >out.sql
deixa o cálculo para bashtail -n +16224
para reduzir a computaçãoVocê pode usar 'vi' e, em seguida, o seguinte comando:
Alternativamente:
EDIT: - Apenas para adicionar uma explicação, use o comando -n 16482 para exibir as primeiras 16482 linhas e, em seguida, use o tail -n 258 para obter as últimas 258 linhas da primeira saída.
fonte
cat
comando;head
pode ler um arquivo diretamente. Isso é mais lento que muitas alternativas porque usa 2 (3 como mostrado) comandos em que 1 é suficiente.cat
). Outras soluções precisam de pelo menos alguns minutos. Também parece ser a variação mais rápida no GNUtail -n +XXX filename | head XXX
.Há outra abordagem com
awk
:Se o arquivo for grande, pode ser bom
exit
depois de ler a última linha desejada. Dessa forma, ele não lerá as seguintes linhas desnecessariamente:fonte
print; exit
. Obrigado !awk 'NR==16224, NR==16482; NR==16482 {exit}' file
fonte
fonte
deve fazer o truque. A desvantagem dessa abordagem é que você precisa fazer a aritmética para determinar o argumento da cauda e explicar se deseja que o 'entre' inclua a linha final ou não.
fonte
cat
comando;head
pode ler um arquivo diretamente. Isso é mais lento que muitas alternativas porque usa 2 (3 como mostrado) comandos em que 1 é suficiente.| tail -$((16482 - 16224))
.De pé sobre os ombros de boxxar, eu gosto deste:
por exemplo
Como
$
significa "última linha", o primeiro comando faz com quesed
todas as linhas sejam impressas começando com a linha16224
e o segundo comando ésed
encerrado após a impressão da linha16428
. (Adicionando1
para oq
Parece não ser necessário intervalo na solução de boxxar.)Eu gosto dessa variante porque não preciso especificar o número da linha final duas vezes. E eu medi que o uso
$
não tem efeitos prejudiciais no desempenho.fonte
sed -n '16224,16482p' < dump.sql
fonte
Rapido e sujo:
Provavelmente não é a melhor maneira de fazê-lo, mas deve funcionar.
BTW: 259 = 16482-16224 + 1.
fonte
Eu escrevi um programa Haskell chamado splitter que faz exatamente isso: leia a publicação do meu blog de lançamento .
Você pode usar o programa da seguinte maneira:
E isso é tudo o que há para isso. Você precisará do Haskell para instalá-lo. Somente:
E você terminou. Espero que você ache este programa útil.
fonte
splitter
somente leitura da entrada padrão? Em certo sentido, isso não importa; ocat
comando é supérfluo, independentemente de existir ou não. Usesplitter 16224-16482 < somefile
ou (se houver argumentos de nome de arquivo)splitter 16224-16482 somefile
.Mesmo nós podemos fazer isso para verificar na linha de comando:
Por exemplo:
fonte
cat
comando em nenhum deles;sed
é perfeitamente capaz de ler arquivos por conta própria ou você pode redirecionar a entrada padrão de um arquivo.Usando ruby:
fonte
Eu estava prestes a postar o truque de cabeça / cauda, mas na verdade eu provavelmente iria iniciar o emacs. ;-)
abra o novo arquivo de saída, salve ctl-y
Vamos ver o que está acontecendo.
fonte
Eu usaria:
FNR contém o número do registro (linha) da linha que está sendo lida no arquivo.
fonte
Eu queria fazer a mesma coisa a partir de um script usando uma variável e consegui-o colocando aspas em torno da variável $ para separar o nome da variável do p:
Eu queria dividir uma lista em pastas separadas e encontrei a pergunta inicial e respondi a uma etapa útil. (comando split não é uma opção no sistema operacional antigo para o qual tenho que portar o código).
fonte
Eu escrevi um pequeno script bash que você pode executar a partir da linha de comando, desde que atualize seu PATH para incluir seu diretório (ou você pode colocá-lo em um diretório que já esteja contido no PATH).
Uso: $ pinch filename start-line end-line
fonte
wc
comando, que desperdiça largura de banda do disco, especialmente em arquivos de gigabyte. De todas as formas, isso está bem documentado, mas também é um exagero de engenharia.Isso pode funcionar para você (GNU sed):
ou aproveitando o bash:
fonte
Usando ed:
-s
suprime a saída de diagnóstico; os comandos reais estão em uma string here. Especificamente,16224,16482p
executa op
comando (impressão) no intervalo de endereços de linha desejado.fonte
O -n nas respostas de aceitação funciona. Aqui está outra maneira, caso você esteja inclinado.
Isso faz o seguinte:
fonte
cat file | sed
é melhor escrita comosed file
Como estamos falando de extrair linhas de texto de um arquivo de texto, darei um caso especial em que você deseja extrair todas as linhas que correspondem a um determinado padrão.
Irá imprimir a linha [Dados] e o restante. Se você quiser o texto da linha1 para o padrão, digite: sed -n '1, / Data / p' myfile. Além disso, se você conhece dois padrões (melhor ser exclusivo em seu texto), tanto a linha inicial quanto a final do intervalo podem ser especificadas com correspondências.
fonte