Pergunta

Eu tenho uma linha de despejo ~ 23000 SQL contendo vários bancos de dados no valor de dados. Eu preciso extrair uma determinada seção deste arquivo (ou seja, os dados de um único banco de dados) e colocá-lo em um novo arquivo. Eu sei que ambos os números de linha de início e fim dos dados que eu quero.

Alguém sabe um comando Unix (ou série de comandos) para extrair todas as linhas de um arquivo entre a linha digamos 16224 e 16482 e, em seguida, redirecioná-los em um novo arquivo?

Foi útil?

Solução

sed -n '16224,16482p;16483q' filename > newfile

A partir da sed manual do :

p - Imprimir o espaço de padrões (para a saída padrão). Este comando é geralmente utilizado em conjunto com a opção de linha de comando -n.

n - Se auto-print não está desativado, imprimir o espaço de padrões, então, independentemente, substitua o espaço de padrões com a próxima linha de entrada. E se não há mais entrada, em seguida, sed sai sem processamento mais comandos.

q - sed sair sem processar qualquer mais comandos ou entrada. Note-se que o espaço atual padrão é impresso se auto-impressão não é desativado com a opção -n.

e

Endereços em um script sed pode estar em qualquer das seguintes formas:

número Especificando um número de linha irá corresponder apenas a linha na entrada.

Um intervalo de endereços pode ser especificado, especificando dois endereços separadas por uma vírgula (,). Um intervalo de endereços corresponda a partir de linhas onde o primeiro endereço de jogos, e continua até que o segundo partidas de endereço (inclusive).

Outras dicas

sed -n '16224,16482 p' orig-data-file > new-file

Onde 16224,16482 são o número da linha de início e número da linha final, inclusive. Este é um indexado. suprime -n ecoando a entrada como de saída, que você claramente não quer; Os números indicam a gama de linhas para fazer o seguinte comando operar; os comandos p imprime as linhas relevantes.

Muito simples usando cabeça / cauda:

head -16482 in.sql | tail -258 > out.sql

usando sed:

sed -n '16482,16482p' in.sql > out.sql

usando awk:

awk 'NR>=10&&NR<=20' in.sql > out.sql

Você pode usar 'vi' e, em seguida, o seguinte comando:

:16224,16482w!/tmp/some-file

Como alternativa:

cat file | head -n 16482 | tail -n 258

EDIT: - Só para acrescentar explicação, você usa cabeça -n 16482 para exibir primeiro 16482 linhas, em seguida, usar tail -n 258 para obter últimos 258 linhas fora do primeira saída.

Há uma outra abordagem com awk:

awk 'NR==16224, NR==16482' file

Se o arquivo é enorme, pode ser bom para exit depois de ler a última linha desejada. Desta forma, ele não vai ler as seguintes linhas desnecessariamente:

awk 'NR==16224, NR==16482-1; NR==16482 {print; exit}' file
perl -ne 'print if 16224..16482' file.txt > new_file.txt
 # print section of file based on line numbers
 sed -n '16224 ,16482p'               # method 1
 sed '16224,16482!d'                 # method 2

sed -n '16224,16482p' < dump.sql

cat dump.txt | head -16224 | tail -258

deve fazer o truque. A desvantagem dessa abordagem é que você precisa fazer a aritmética para determinar o argumento para a cauda e conta para se deseja que o 'entre' para incluir a linha que termina ou não.

rápido e sujo:

head -16428 < file.in | tail -259 > file.out

Provavelmente não é a melhor maneira de fazê-lo, mas ele deve funcionar.

BTW:. 259 = 16482-16224 + 1

Eu escrevi um programa Haskell chamada divisor que faz exatamente isso: ter um ler o meu blog liberação .

Você pode usar o programa da seguinte forma:

$ cat somefile | splitter 16224-16482

E isso é tudo que existe para ela. Você vai precisar de Haskell para instalá-lo. Just:

$ cabal install splitter

E está feito. Espero que você encontrar este programa útil.

Mesmo que nós podemos fazer isso para verificar a linha de comando:

cat filename|sed 'n1,n2!d' > abc.txt

Por exemplo:

cat foo.pl|sed '100,200!d' > abc.txt

Usando ruby:

ruby -ne 'puts "#{$.}: #{$_}" if $. >= 32613500 && $. <= 32614500' < GND.rdf > GND.extract.rdf

pé sobre os ombros de boxxar, eu como este:

sed -n '<first line>,$p;<last line>q' input

por exemplo.

sed -n '16224,$p;16482q' input

O meio $ "última linha", de modo que o primeiro comando faz sed imprimir todas as linhas que começam com linha 16224 e o segundo comando faz sed parar após imprimir 16428 line. (Adicionando 1 para o q-range em solução de boxxar não parece ser necessário.)

Eu gosto desta variante, porque não é necessário especificar o número da linha terminando duas vezes. E eu medida que o uso de $ não tem efeitos prejudiciais sobre o desempenho.

Eu estava prestes a publicar o truque de cabeça / cauda, ??mas na verdade eu provavelmente só fogo até emacs. ; -)

  1. esc - x Goto-line ret 16224
  2. marca ( Ctrl - espaço )
  3. esc - x Goto-line ret 16482
  4. esc - w

abrir o novo arquivo de saída, ctl-y save

Vamos ver-me o que está acontecendo.

Gostaria de usar:

awk 'FNR >= 16224 && FNR <= 16482' my_file > extracted.txt

FNR contém o número de registro (linha) da linha a ser lido a partir do arquivo.

Eu escrevi um script pequeno que você pode executar a partir de sua linha de comando, desde que você atualizar seu PATH para incluir seu diretório (ou você pode colocá-lo em um diretório que já está contido no PATH).

Uso: $ beliscar filename iniciar-line end-line

#!/bin/bash
# Display line number ranges of a file to the terminal.
# Usage: $ pinch filename start-line end-line
# By Evan J. Coon

FILENAME=$1
START=$2
END=$3

ERROR="[PINCH ERROR]"

# Check that the number of arguments is 3
if [ $# -lt 3 ]; then
    echo "$ERROR Need three arguments: Filename Start-line End-line"
    exit 1
fi

# Check that the file exists.
if [ ! -f "$FILENAME" ]; then
    echo -e "$ERROR File does not exist. \n\t$FILENAME"
    exit 1
fi

# Check that start-line is not greater than end-line
if [ "$START" -gt "$END" ]; then
    echo -e "$ERROR Start line is greater than End line."
    exit 1
fi

# Check that start-line is positive.
if [ "$START" -lt 0 ]; then
    echo -e "$ERROR Start line is less than 0."
    exit 1
fi

# Check that end-line is positive.
if [ "$END" -lt 0 ]; then
    echo -e "$ERROR End line is less than 0."
    exit 1
fi

NUMOFLINES=$(wc -l < "$FILENAME")

# Check that end-line is not greater than the number of lines in the file.
if [ "$END" -gt "$NUMOFLINES" ]; then
    echo -e "$ERROR End line is greater than number of lines in file."
    exit 1
fi

# The distance from the end of the file to end-line
ENDDIFF=$(( NUMOFLINES - END ))

# For larger files, this will run more quickly. If the distance from the
# end of the file to the end-line is less than the distance from the
# start of the file to the start-line, then start pinching from the
# bottom as opposed to the top.
if [ "$START" -lt "$ENDDIFF" ]; then
    < "$FILENAME" head -n $END | tail -n +$START
else
    < "$FILENAME" tail -n +$START | head -n $(( END-START+1 ))
fi

# Success
exit 0

Este trabalho poder para você (GNU sed):

sed -ne '16224,16482w newfile' -e '16482q' file

ou aproveitando bash:

sed -n $'16224,16482w newfile\n16482q' file

Eu queria fazer a mesma coisa a partir de um script usando uma variável e alcançou-lo, colocando aspas em torno dos US $ variável para separar o nome da variável a partir da p:

sed -n "$first","$count"p imagelist.txt >"$imageblock"

Eu queria dividir uma lista em pastas separadas e encontrou a questão inicial e responder a um passo útil. (Comando split não é uma opção sobre o antigo sistema operacional tenho de código de porta a).

O -n no aceitar respostas trabalho. Aqui está outra maneira no caso de você está inclinado.

cat $filename | sed "${linenum}p;d";

Este faz o seguinte:

  1. tubulação no conteúdo de um arquivo (ou alimentação no texto como quiser).
  2. seleciona sed a linha dada, imprime-
  3. d é necessário para linhas de exclusão, caso contrário, sed irá assumir todas as linhas acabará por ser impressos. ou seja, sem a d, você terá todas as linhas impressas pela linha selecionada impressa duas vezes, porque você tem a parte $ {linenum} p pedindo para que ela seja impressa. Eu tenho certeza que a -n é basicamente fazer a mesma coisa que o d aqui.

Uma vez que estamos a falar de extrair linhas de texto a partir de um arquivo de texto, vou dar um caso especial em que você deseja extrair todas as linhas que correspondam a um determinado padrão.

myfile content:
=====================
line1 not needed
line2 also discarded
[Data]
first data line
second data line
=====================
sed -n '/Data/,$p' myfile

Será imprimir a linha [de dados] e os restantes. Se você deseja que o texto a partir line1 ao padrão, você digita: '1, / Dados p /' myfile sed -n. Além disso, se você sabe dois padrão (melhor ser único no seu texto), a linha de início e final do intervalo pode ser especificado com fósforos.

sed -n '/BEGIN_MARK/,/END_MARK/p' myfile

Eu acho que isso pode ser uma solução útil. Se o nome da tabela é "pessoa" Você pode usar sed para obter todas as linhas que você precisa para restaurar sua mesa.

sed -n -e '/DROP TABLE IF EXISTS.*`person `/,/UNLOCK TABLES/p' data.sql  > new_data.sql

Com base esta resposta , onde ele está faltando o "DROP TABLE IF EXIST" para a tabela que você está restaurando e você precisa excluir algumas linhas a partir da parte inferior do novo arquivo antes de usá-lo para evitar excluir a tabela seguinte.

Informações detalhadas podem ser encontradas também aqui

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top