it-swarm-tr.com

Önceden belirlenmiş bir satır aralığını Unix'teki bir metin dosyasından nasıl çıkarabilirim?

Veri değerinde birkaç veritabanı içeren bir ~ 23000 satır SQL dökümü var. Bu dosyanın belirli bir bölümünü çıkarmam gerekiyor (yani, tek bir veritabanının verileri) ve yeni bir dosyaya yerleştirmem gerekiyor. İstediğim verilerin hem başlangıç ​​hem de bitiş satırı numaralarını biliyorum.

Bir satırdaki 16224 ile 16482 arasındaki bir dosyadaki tüm satırları ayıklamak ve daha sonra bunları yeni bir dosyaya yönlendirmek için bir Unix komutu (veya bir dizi komut) bilen var mı?

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

sed kılavuzundan :

p - Desen alanını yazdırın (standart çıktıya). Bu komut genellikle sadece -n komut satırı seçeneğiyle birlikte kullanılır.

n - Otomatik yazdırma devre dışı değilse, desen alanını yazdırın, ardından desen alanını sonraki giriş satırıyla değiştirin. Eğer daha fazla girdi yok, sonra sed, daha fazla işlem yapmadan çıkar. emreder.

q - Daha fazla komut işlemeden veya giriş yapmadan sed çıkın . -N seçeneğiyle otomatik yazdırma devre dışı bırakılmazsa, geçerli desen alanının yazdırıldığını unutmayın.

ve

Sed komut dosyasındaki adresler, aşağıdaki formlardan birinde olabilir:

numara Bir satır numarası belirlemek, girişte yalnızca o satırla eşleşecektir.

İki adres belirtilerek bir adres aralığı belirtilebilir virgülle ayrılmış (,). Bir adres aralığı, .__ ile başlayan satırlarla eşleşir. ilk adres eşleşir ve ikinci olana kadar devam eder. adres eşleşmeleri (özel olarak).

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

16224,16482, başlangıç ​​satırı numarası ve bitiş satırı numarası ise dahil. Bu 1 indeksli. -n, girişin açıkça istemediğiniz çıkış olarak yankılanmasını önler; sayılar, aşağıdaki komutu çalıştırmak için satır aralığını gösterir; p komutu ilgili satırları yazdırır.

195
JXG

Baş/kuyruk kullanarak oldukça basit:

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

sed kullanarak:

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

awk kullanarak:

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

'Vi' ve sonra şu komutu kullanabilirsiniz:

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

Alternatif: 

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

EDIT: - Sadece açıklama eklemek için, ilk 16482 satırı görüntülemek için head -n 16482 tuşlarını kullanın, ardından ilk çıkıştan son 258 satırı almak için tail -n 258 tuşlarını kullanın. 

25
Mark Janssen

awk ile başka bir yaklaşım daha var:

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

Dosya çok büyükse, son istenen satırı okuduktan sonra exit işlevi iyi olabilir. Bu şekilde, sonuna kadar dosyayı gereksiz yere okumaz:

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

hile yapmalı. Bu yaklaşımın dezavantajı, kuyruğun argümanını belirlemek için aritmetiği yapmanız ve 'arasında' bitiş çizgisini içermesini isteyip istemediğinizi hesaplamanız gerektiğidir.

5
JP Lodine

Hızlı ve kirli:

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

Muhtemelen bunu yapmanın en iyi yolu değil ama çalışması gerekir.

BTW: 259 = 16482-16224 + 1.

3
jan.vdbergh

Baş/kuyruk numarasını göndermek üzereydim, ama aslında ben sadece emacs ateşlerdim. ;-)

  1. esc-x git-line ret 16224
  2. işaret (ctrl-space)
  3. esc-x git-line ret 16482
  4. esc-w

yeni çıktı dosyasını açın, ctl-y save

Bakalım neler oluyor.

3
sammyo

Biz bile bunu komut satırından kontrol etmek için yapabiliriz:

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

Örneğin:

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

Ruby kullanarak:

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

Kullanmak istiyorum:

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

FNR, dosyadan okunmakta olan satırın kayıt (satır) numarasını içerir.

2
Paddy3118

Tam olarak bunu yapan splitter adında bir Haskell programı yazdım: yayın bülten yayınımı oku.

Programı aşağıdaki gibi kullanabilirsiniz:

$ cat somefile | splitter 16224-16482

Ve hepsi bu kadar var. Yüklemek için Haskell'e ihtiyacınız olacak. Sadece:

$ cabal install splitter

Ve bitti. Umarım bu programı faydalı bulursunuz.

2
Robert Massaioli

Bu sizin için işe yarayabilir (GNU sed):

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

veya bash'den yararlanmak:

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

PATH'nizi dizinini içerecek şekilde güncellediğiniz sürece (ya da PATH içinde bulunan bir dizine yerleştirebilirsiniz) komut satırından çalıştırabileceğiniz küçük bir bash komut dosyası yazdım.

Kullanımı: $ tutam dosya adı başlangıç ​​satırı bitiş satırı

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

Aynı şeyi bir değişken kullanarak bir betikten de yapmak istedim ve değişken ismini p'den ayırmak için $ değişkeninin etrafına tırnak koyarak bunu başardım:

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

Bir listeyi ayrı klasörlere bölmek ve ilk soruyu bulmak ve yararlı bir adımı cevaplamak istedim. (split komutu eski os'ta bir seçenek değil, port kodunu vermem gerekiyor).

1
KevinY

Bir metin dosyasından metin satırlarını çıkarmak hakkında konuştuğumuz için, belirli bir kalıpla eşleşen tüm satırları çıkarmak istediğiniz özel bir durum vereceğim. 

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

[Data] satırını ve kalanını basacaktır. Satır1'den desene metni istiyorsanız, şunu yazın: sed -n '1,/Data/p' dosyam. Ayrıca, iki desen biliyorsanız (metninizde benzersiz olsa da), aralığın hem başlangıç ​​hem de bitiş çizgisi eşleşmelerle belirtilebilir.

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

Boxxar'ın omuzlarında dururken, şunu beğendim:

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

Örneğin.

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

$ "son satır" anlamına gelir, bu nedenle ilk komut sed __ satır 16224 ile başlayan tüm satırları yazdırır ve ikinci komut sed quit after print line 16428 yapar. (Boxxar'ın çözümünde q- aralığı için 1 eklemek gerekli görünmüyor.)

Bu değişkeni seviyorum çünkü bitiş satırı numarasını iki kez belirtmem gerekmiyor. Ve $ kullanmanın performans üzerinde zararlı bir etkisi olmadığını ölçtüm.

0
Tilman Vogel

Kabul etme cevaplarındaki -n çalışması. İşte size eğimli olması durumunda başka bir yol.

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

Bu, aşağıdakileri yapar:

  1. bir dosyanın içeriğini belirtmek (veya istediğiniz şekilde metinde beslemek).
  2. sed verilen satırı seçer, yazdırır
  3. d satırları silmek için gereklidir, aksi halde sed tüm satırların sonunda yazdırılacağını varsayar. yani, d olmadan, seçilen satır tarafından yazdırılan tüm satırları iki kez yazdırırsınız, çünkü $ {linenum} p kısmı yazdırılmasını ister. Eminim ki -n aslında burada d ile aynı şeyi yapıyor.
0
ThinkBonobo