it-swarm-eu.dev

Jak mohu extrahovat předem určený rozsah řádků z textového souboru na Unixu?

Mám ~ 23000 řádek SQL výpis obsahující několik databází v hodnotě dat. Potřebuji extrahovat určitou část tohoto souboru (tj. Data pro jednu databázi) a umístit ji do nového souboru. Znám čísla počátečního i koncového řádku dat, která chci.

Zná někdo příkaz Unix (nebo sérii příkazů), který má extrahovat všechny řádky ze souboru mezi řádky 16224 a 16482 a pak je přesměrovat do nového souboru?

447
Adam J. Forster
sed -n '16224,16482p;16483q' filename > newfile

Z manuálu :

p - Vytiskne prostor vzoru (na standardní výstup). Tento příkaz se obvykle používá pouze ve spojení s volbou -n příkazového řádku.

n - Není-li automatický tisk zakázán, vytiskněte prostor vzorů a pak bez ohledu na to nahraďte prostor vzoru dalším řádkem vstupu. Jestliže Není více vstupů, pak sed končí bez zpracování dalších Příkazů.

q - Ukončete sed bez zpracování dalších příkazů nebo vstupů. Všimněte si, že pokud není automatický tisk zakázán volbou -n, vytiskne se aktuální prostor vzorů.

a

Adresy ve skriptu sed mohou být v následujících formách:

number Zadání čísla řádku se bude shodovat pouze s tímto řádkem na vstupu.

Rozsah adres lze zadat zadáním dvou adres Oddělených čárkou (,). Rozsah adres se shoduje s řádky začínajícími od , Kde se první adresa shoduje, a pokračuje až do druhé shody adresy (Včetně).

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

Tam, kde 16224,16482 jsou číslo počáteční linie a číslo koncového řádku, včetně. Toto je 1-indexované. -n potlačuje ozvěnu vstupu jako výstupu, který zřejmě nechcete; čísla označují rozsah řádků, na kterých se má provádět následující příkaz; příkaz p vytiskne příslušné řádky.

195
JXG

Poměrně jednoduché použití hlavy/ocasu:

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

pomocí sed:

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

pomocí awk:

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

Můžete použít příkaz „vi“ a poté následující příkaz:

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

Alternativně: 

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

EDIT: - Pro přidání vysvětlení použijete head -n 16482 pro zobrazení prvních 16482 řádků, pak použijte tail -n 258 pro získání posledních 258 řádků z prvního výstupu. 

25
Mark Janssen

Existuje další přístup s awk:

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

Pokud je soubor obrovský, může být dobré po exit po přečtení posledního požadovaného řádku. Tímto způsobem soubor zbytečně přečte až do konce:

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

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

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

by měl udělat trik. Nevýhodou tohoto přístupu je to, že musíte udělat aritmetiku, abyste určili argument pro ocas, a abyste zjistili, zda chcete, aby „mezi“ zahrnoval koncový řádek nebo ne.

5
JP Lodine

Rychle a špinavě:

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

Pravděpodobně to není nejlepší způsob, jak to udělat, ale mělo by to fungovat.

BTW: 259 = 16482-16224 + 1.

3
jan.vdbergh

Chystal jsem se poslat trik na hlavu/ocas, ale ve skutečnosti bych asi vypálil emacs. ;-)

  1. esc-x goto-line ret 16224
  2. značka (ctrl-space)
  3. esc-x goto-line ret 16482
  4. esc-w

otevřete nový výstupní soubor, ctl-y save

Uvidíme, co se děje.

3
sammyo

Můžeme to udělat i na příkazovém řádku:

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

Například:

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

Použití Ruby:

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

Použil bych:

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

FNR obsahuje číslo záznamu (řádku) čtecího řádku ze souboru.

2
Paddy3118

Napsal jsem program Haskell nazvaný splitter který dělá přesně toto: mít číst přes můj příspěvek blogu .

Program můžete použít následovně:

$ cat somefile | splitter 16224-16482

A to je vše, co tam je. K instalaci budete potřebovat Haskell. Prostě:

$ cabal install splitter

A jste hotovi. Doufám, že tento program bude užitečný.

2
Robert Massaioli

To by mohlo fungovat pro vás (GNU sed):

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

nebo využití bash:

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

Napsal jsem malý bash skript, který můžete spustit z příkazového řádku, pokud aktualizujete PATH tak, aby obsahoval jeho adresář (nebo jej můžete umístit do adresáře, který je již obsažen v PATH).

Použití: $ pinch filename start-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
1
Nerdfighter

Chtěl jsem udělat totéž ze skriptu s použitím proměnné a dosáhnout toho tím, že vložím uvozovky kolem proměnné $ a oddělím název proměnné od p:

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

Chtěl jsem rozdělit seznam do samostatných složek a najít počáteční otázku a odpovědět na užitečný krok. (rozdělit příkaz není volba na starém OS musím kód portu na).

1
KevinY

Protože hovoříme o extrahování řádků textu z textového souboru, dám zvláštní případ, kdy chcete extrahovat všechny řádky, které odpovídají určitému vzoru. 

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

Vytiskne řádek [Data] a zbývající. Pokud chcete, aby text z řádku 1 do vzoru, zadejte: sed -n '1,/Data/p' myfile. Kromě toho, pokud znáte dva vzory (lepší ve vašem textu), lze počáteční i koncový řádek rozsahu určit pomocí shod.

sed -n '/BEGIN_MARK/,/END_MARK/p' myfile
0
Kemin Zhou

Stál na ramenou boxxaru, líbí se mi to:

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

např.

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

$ znamená "poslední řádek", takže první příkaz sed vytiskne všechny řádky začínající řádkem 16224 a druhý příkaz sed quit after print line 16428. (Přidání 1 pro q-range v řešení boxxaru se nezdá být nezbytné.)

Líbí se mi tato varianta, protože nemusím zadávat číslo koncového řádku dvakrát. A měřil jsem, že použití $ nemá škodlivé účinky na výkon.

0
Tilman Vogel

-N v přijímací odpovědi práce. Tady je další způsob, pokud jste nakloněni.

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

To dělá následující:

  1. v obsahu souboru (nebo zdroj v textu, který chcete).
  2. sed vybere danou linku, vytiskne ji
  3. d je nutné k vymazání řádků, jinak se předpokládá, že všechny řádky budou nakonec vytištěny. tj. bez d, dostanete všechny řádky vytištěny vybraným řádkem vytištěným dvakrát, protože máte $ {linenum} p část, která žádá o jeho tisk. Jsem si jistý, že -n v podstatě dělá totéž, co tady d.
0
ThinkBonobo