Domanda

Ho un dump SQL di ~ 23000 righe contenente diversi database di dati.Devo estrarre una determinata sezione di questo file (ad es.i dati per un singolo database) e inserirlo in un nuovo file.Conosco sia il numero di riga iniziale che quello finale dei dati che desidero.

Qualcuno conosce un comando Unix (o una serie di comandi) per estrarre tutte le righe da un file tra, ad esempio, la riga 16224 e 16482 e quindi reindirizzarle in un nuovo file?

È stato utile?

Soluzione

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

Dal manuale sed:

P - Stampa lo spazio del motivo (all'uscita standard).Questo comando viene solitamente utilizzato solo insieme all'opzione -n ​​della riga di comando.

N - Se la stampa automatica non è disabilitata, stampare lo spazio del motivo, quindi, a prescindere, sostituire lo spazio del modello con la riga di input successiva.Se non ci sono più input, SED esce senza ulteriori comandi.

Q - Uscita sed senza elaborare altri comandi o input.Tieni presente che lo spazio del pattern corrente viene stampato se la stampa automatica non è disabilitata con l'opzione -n.

E

Gli indirizzi in uno script sed possono essere in una delle seguenti forme:

numeroSpecificando un numero di riga corrisponderà solo a quella riga nell'input.

Un intervallo di indirizzi può essere specificato specificando due indirizzi separati da una virgola (,).Un intervallo di indirizzi corrisponde alle righe a partire da dove si abbina il primo indirizzo e continua fino a quando il secondo indirizzo non corrisponde (inclusivo).

Altri suggerimenti

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

Dove 16224,16482 sono il numero della linea di partenza e il numero della linea di fine, inclusi.Questo è indicizzato 1. -n sopprime l'eco dell'input come output, cosa che chiaramente non vuoi;i numeri indicano l'intervallo di righe su cui operare il comando successivo;il comando p stampa le righe pertinenti.

Abbastanza semplice usando testa/coda:

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

Potresti usare 'vi' e poi il seguente comando:

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

In alternativa:

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

EDIT: - Solo per aggiungere una spiegazione, usi testa -n 16482 per visualizzare le prime 16482 righe quindi utilizzare coda -n 258 per ottenere le ultime 258 righe dal primo output.

C'è un altro approccio con awk:

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

Se il file è enorme, può essere utile exit dopo aver letto l'ultima riga desiderata.In questo modo non leggerà inutilmente le seguenti righe:

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

dovrebbe fare il trucco.Lo svantaggio di questo approccio è che è necessario eseguire operazioni aritmetiche per determinare l'argomento per tail e per tenere conto se si desidera che il "tra" includa o meno la riga finale.

Veloce e sporco:

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

Probabilmente non è il modo migliore per farlo, ma dovrebbe funzionare.

A proposito:259 = 16482-16224+1.

Ho scritto un programma Haskell chiamato divisore fa esattamente questo:avere un leggi il mio post sul blog di rilascio.

È possibile utilizzare il programma come segue:

$ cat somefile | splitter 16224-16482

E questo è tutto.Avrai bisogno di Haskell per installarlo.Appena:

$ cabal install splitter

E il gioco è fatto.Spero che troverai utile questo programma.

Anche noi possiamo farlo per controllare dalla riga di comando:

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

Per esempio:

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

Usando il rubino:

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

In piedi sulle spalle di boxxar, mi piace questo:

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

per esempio.

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

IL $ significa "ultima riga", quindi il primo comando rende sed stampa tutte le righe che iniziano con riga 16224 e il secondo comando fa sed esentato Dopo linea di stampa 16428.(Aggiungendo 1 per il q-range nella soluzione di boxxar non sembra essere necessario.)

Mi piace questa variante perché non ho bisogno di specificare due volte il numero della riga finale.E l'ho misurato utilizzando $ non ha effetti negativi sulle prestazioni.

Stavo per pubblicare il trucco testa/coda, ma in realtà probabilmente avrei semplicemente avviato emacs.;-)

  1. Esc-X goto-line ritirarsi 16224
  2. segno (Ctrl-spazio)
  3. Esc-X goto-line ritirarsi 16482
  4. Esc-w

Apri il nuovo file di output, CTL-Y salva

Fammi vedere cosa sta succedendo.

Io userei:

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

FNR contiene il numero di record (riga) della riga letta dal file.

Ho scritto un piccolo script bash che puoi eseguire dalla riga di comando, purché aggiorni il tuo PERCORSO per includere la sua directory (oppure puoi inserirlo in una directory già contenuta nel PERCORSO).

Utilizzo:$ pizzica nome file riga di inizio riga di fine

#!/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

Questo potrebbe funzionare per te (GNU sed):

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

o approfittando di bash:

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

Volevo fare la stessa cosa da uno script utilizzando una variabile e l'ho ottenuto inserendo virgolette attorno alla variabile $ per separare il nome della variabile dalla p:

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

Volevo dividere un elenco in cartelle separate e ho trovato la domanda iniziale e la risposta un passaggio utile.(il comando split non è un'opzione sul vecchio sistema operativo su cui devo trasferire il codice).

La -n nelle risposte accetta funziona.Ecco un altro modo nel caso tu sia propenso.

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

Questo fa quanto segue:

  1. Inserisci il contenuto di un file (o inserisci il testo come preferisci).
  2. sed seleziona la riga data e la stampa
  3. d è necessario per eliminare le righe, altrimenti sed presumerà che tutte le righe alla fine verranno stampate.cioè, senza la d, tutte le righe stampate dalla riga selezionata verranno stampate due volte perché hai la parte ${linenum}p che richiede che venga stampata.Sono abbastanza sicuro che -n stia sostanzialmente facendo la stessa cosa di d qui.

Poiché stiamo parlando di estrarre righe di testo da un file di testo, fornirò un caso speciale in cui desideri estrarre tutte le righe che corrispondono a un determinato modello.

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

Stamperà la riga [Dati] e il resto.Se vuoi il testo dalla riga 1 al pattern, digita:sed -n '1,/Dati/p' miofile.Inoltre, se conosci due modelli (meglio che siano univoci nel testo), sia la riga iniziale che quella finale dell'intervallo possono essere specificate con corrispondenze.

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

Penso che questa potrebbe essere una soluzione utile.Se il nome della tabella è "person" puoi utilizzare sed per ottenere tutte le righe necessarie per ripristinare la tabella.

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

Basato su questa risposta, dove manca "DROP TABLE IF EXIST" per la tabella che stai ripristinando ed è necessario eliminare alcune righe dalla fine del nuovo file prima di utilizzarlo per evitare di eliminare la tabella successiva.

È inoltre possibile trovare informazioni dettagliate Qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top