Linux'ta bir metin dosyasındaki belirli satırlar nasıl gösterilir?


85

Sanırım herkes faydalı Linux cmd satırı araçlarını headve biliyor tail. headBir dosyanın ilk X satırını yazdırmanıza izin verir tail, aynısını yapar ancak dosyanın sonunu basar. Bir dosyanın ortasını yazdırmak için iyi bir komut nedir? gibi bir şey middle --start 10000000 --count 20(10.000’e 10.000’deki 10.00’a kadar olan satırları yazdırın).

Verimli büyük dosyaları ile ilgilenecek bir şey arıyorum. Denedim tail -n 10000000 | head 10ve çok yavaş.


Yanıtlar:


111
sed -n '10000000,10000020p' filename

Bunu biraz daha hızlandırabilirsin:

sed -n '10000000,10000020p; 10000021q' filename

Bu komutların, seçenek -nneden sed"desen alanının otomatik baskı bastırmak". pKomut "Baskı [s] Geçerli desen alanı" ve qkomut "Derhal bir daha girdi işlemeden [s] sed komut dosyası çıkın ..." tırnak gelmektedir sed mansayfa .

Bu arada, emriniz

tail -n 10000000 filename | head 10

dan on milyonuncu satırında başlar sonuna sizin "orta" komutu on milyonda başlayacak gibi görünüyor ise dosyanın, başından eşdeğer olacaktır:

head -n 10000010 filename | tail 10

Sorun, değişken uzunluklu satırlara sahip sıralanmamış dosyalar için herhangi bir işlemin dosya sayma yeni satırlarını incelemesi gerekmesidir. Kısayol yapmanın yolu yok.

Bununla birlikte, dosya sıralanırsa (örneğin, zaman damgası olan bir günlük dosyası) veya sabit uzunluk çizgileri varsa, o zaman bayt konumunu temel alarak dosyayı arayabilirsiniz. Günlük dosyası örnekte, benim Python komut dosyası olarak kez aralığı için bir ikili arama yapabileceğini burada * yapar. Sabit kayıt uzunluğu dosyası durumunda, bu gerçekten kolay. Sadece linelength * linecountdosyaya karakterleri ararsınız.

* Ben o betiğe başka bir güncelleme göndermek anlamına gelir. Belki bugünlerden biriyle uğraşırım.


İşte olan sedCharles'ın sürüm middlefonksiyonu: middle() { local s=$1 c=$2; shift 2; sed -n "$s,$(($s + $c -1))p; $(($s + $c))q" "$@"; }. Onlar aynı şekilde catted sanki birden fazla dosya birlikte işlenir vb çoklu dosya argümanlar, boşluklarla dosya, idare edecek sed1000 100 dosya1 dosya2 başlangıcına birinci dosyanın sonuna genelinde yayılan bu yüzden orta normalde ( İkincisi 1100 satırdan azsa
Dennis Williamson,

Önceki yorumumdaki işlev bir dosya adı parametresiyle: middle startline count filenameveya birden fazla dosya adıyla : middle startline count file1 file2 file3veya yeniden yönlendirme ile: middle startline count < filenameveya bir boruda: some_command | orta başlangıç ​​çizgisi sayısı` veyacat file* | middle startline count
Dennis Williamson

`Sed emrinizde 'olmamalı mıdır? Backtick ile çalışmasını sağlayamıyorum ama tek bir alıntı ile iyi çalışıyor.
Ian Hunter

@beanland: Evet, bu bir yazım hatası. Düzelttim. Teşekkürler.
Dennis Williamson

1
@kev: Cevabımı bir açıklama ekledim.
Dennis Williamson,

28

Aşağıdaki kullanımını öğrendim sed

sed -n '10000000,+20p'  filename

Umarım biri için yararlıdır!


Dennis tarafından önerilen son satır argümanına bir alternatif olduğunu bilmek güzel: ikinci bir sed -nargüman olarak satır sayımı oldukça okunabilir kılıyor.
user3123159

Örnek bir kullanım: extract_lines(){sed -n "$1,+$2p" <file>}stdout'a yazar.
user3123159

4

Bu benim ilk gönderim burada! Neyse, bu kolay. Diyelim ki 8872 numaralı satırı file.txt adlı dosyanızdan çekmek istiyorsunuz. İşte nasıl:

cat -n dosyası.txt | grep '^ * 8872'

Şimdi soru bundan sonra 20 satır bulmaktır. Bunu başarmak için

cat -n dosyası.txt | grep -A 20 '^ * 8872'

Etrafındaki veya etrafındaki çizgiler için, grep kılavuzundaki -B ve -C bayraklarına bakın.


Bu teknik olarak doğru ve makul boyutta bir dosyada yapmak için ilginç bir yol olsa da, posterin sorduğu boyuttaki dosyalarla çalışırken etkinliğini merak ediyorum.
Jenny D

Birden çok satır: cat -n file.txt | grep "^ \ s \ + (10 \ | 20 \ | 30) \ s \ +"
Jeffrey Knight

cat -n file.txt | grep '^ *1'Sağ tarafında 1 olan tüm çizgileri verir. Bu teknikle 1. satır nasıl verilir? Biliyorum, saat 1'de gidebilirim ... ama grep nasıl kullanılır?
Sean87,

1

Dennis'in sed cevabı gitmenin yolu. Ancak, bash altında sadece baş ve kuyruk kullanarak:

orta () {head -n $ [1 $ + 2 $] | kuyruk -n2 $; }

Bu, ilk 1 $ + 2 $ çizgisini iki kez tarar, bu yüzden Dennis'in cevabından çok daha kötüdür. Ama kullanmak için tüm bu küçük harfleri hatırlamana gerek yok ....


Kullanımı $[...], en azından Bash'te kullanımdan kaldırılmıştır. Ayrıca, bir dosya parametresi eksik.
Dennis Williamson,

@Dennis: Eksik parametre yok: stdin'de buna göre kullanılması gerekiyor middle 10 10 < /var/log/auth.log.
Charles Stewart,

1

Belirli satır aralığını elde etmek için aşağıdaki komutu kullanın

awk 'NR < 1220974{next}1;NR==1513793{exit}' debug.log | tee -a test.log

Burada debug.log, satır eksik bir dosyadan oluşan bir dosyam ve 1220974 satır numarasından 1513793'e bir dosya test.log dosyasına satırları yazdırmak için kullandım. dizi aralığı yakalamak için yararlı olacağını umuyorum.



Aynı cevap değil. Bu, büyük dosyalar için, dosya boyunca taramaya devam etmek yerine son satırın yazdırılmasından sonra aslında iptal edildiği için daha hızlı olmalıdır.
fobic

0

Bir yakut oneliner versiyonu.

ruby -pe 'next unless $. > 10000000 && $. < 10000020' < filename.txt

Birileri için faydalı olabilir. Dennis ve Dox tarafından sağlanan 'sed' çözümleri, daha hızlı görünmesine rağmen çok güzel.


0

'Nl' kullanabilirsiniz.

nl filename | grep <line_num>

0

Mesela bu awk 20 ile 40 arasındaki satırları basacaktır.

awk '{if ((NR> 20) && (NR <40)) $ 0}' / etc / passwd yazdırabilir


0

Satır numaralarını biliyorsanız, dosyadan 1, 3 ve 5 numaralı satırları almak istediğinizi söyleyin, / etc / passwd:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.