Bir dosyanın son n satırını kaldırmak için sed nasıl kullanılır


155

Bir dosyanın sonundan birkaç n satırı kaldırmak istiyorum . Bu sed kullanılarak yapılabilir mi?

Örneğin, 2'den 4'e kadar olan satırları kaldırmak için kullanabilirim

$ sed '2,4d' file

Ama satır numaralarını bilmiyorum. Son satırı kullanarak silebilirim

$sed $d file

ancak sondan n satırı kaldırmanın yolunu bilmek istiyorum . Lütfen sed veya başka bir yöntem kullanarak bunu nasıl yapacağımı bana bildirin.


2
@arashkordi: Bu, dosyanın en altından değil üstünden bir satır sayısı kullanır.
ams


// Belki soruyu olmadığı kadar daha genel hale getirmek için rephrasing düşünün sadece sed ?
Nathan Basanese

1
sed $d filebir hata döndürür. Bunun yerine, $ d şu şekilde tırnak içinde olmalıdır:sed '$d' file
Akronix

Yanıtlar:


234

Bilmiyorum sedama şununla yapılabilir head:

head -n -2 myfile.txt

19
Basitlik için +1. Eşdeğer sed komutu popo çirkin: sed -e :a -e '$d;N;2,5ba' -e 'P;D' file( ,5son 5 satır için).
Marc B

62
Bunun bazı sürümlerinde çalıştığını head, ancak standart olmadığını unutmayın. Aslında, headeyaletler için standart :The application shall ensure that the number option-argument is a positive decimal integer.
William Pursell

21
@ WilliamPursell'in cevabına eklemek için ... Mac OS varsayılan kabuğunda bu çalışmaz.
JDS

8
BSD'de de değil, ama soru Linux olarak etiketlendi.
ams

5
eksi 1, çünkü osx'e ek olarak bu benim için Ubuntu14'te çalışmıyor -head: illegal line count -- -2
Michael Durrant

30

Sabit kodlama n bir seçenekse, sedlemek için sıralı çağrıları kullanabilirsiniz. Örneğin, son üç satırı silmek için son bir satırı üç kez silin:

sed '$d' file | sed '$d' | sed '$d'

2
Bu, artı -i dosyasını standart çıktıya dökmek yerine yerinde düzenlemek, benim için çalıştı.
WAF

28

Gönderen sed biri gömlekleri :

# delete the last 10 lines of a file
sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # method 1
sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # method 2

Aradığın şey gibi görünüyor.


@Thor, dosyadan kaç satırın kaldırılacağını, 10girişi değiştirerek değiştirebilirsiniz'$d;N;2,10ba'
Alexej Magura

1
@AlexejMagura: Cevabın daha önceki bir versiyonu hakkında yorum yapıyordum.
Thor

22

Eğlenceli, basit sedve tacçözüm:

n=4
tac file.txt | sed "1,$n{d}" | tac

NOT

  • "Kabuğun komuttaki $ndeğişkeni değerlendirmesi için çift ​​tırnak işareti gereklidir sed. Tek tırnaklarda ara değerleme yapılmayacaktır.
  • tacBir edilmektedir catters, bkzman 1 tac
  • {}içinde sedvar ayırmak için olan $nve d(değilse, enterpolasyon olmayan kabuk deneyin $nddeğişkeni)

7
Bilginize hiçbir tacosx
Michael Durrant

1
@MichaelDurrant port info coreutils|| brew info coreutils;
dile

19

Kullanın sed, ancak kabuğun matematiği yapmasına izin verin, amaç dbir aralık vererek komutu kullanmaktır (son 23 satırı kaldırmak için):

sed -i "$(($(wc -l < file)-22)),\$d" file

Son 3 satırı içten dışa çıkarmak için:

$(wc -l < file)

Dosyanın satır sayısını verir: 2196

Son 23 satırı kaldırmak istiyoruz, bu nedenle sol taraf veya aralık için:

$((2196-22))

Verir: 2174 Böylece, kabuk yorumlamasından sonraki orijinal sed:

sed -i '2174,$d' file

İle -iINPLACE düzenlemeyi yapıyor, dosya artık 2173 çizgiler!

Yeni bir dosyaya kaydetmek istiyorsanız, kod:

sed -i '2174,$d' file > outputfile

17

Bunun için kafa kullanabilirsin .

Kullanım

$ head --lines=-N file > new_file

burada N, dosyadan kaldırmak istediğiniz satır sayısıdır.

Orijinal dosyanın içeriği eksi son N satır şimdi new_file'da


8

Tamlık için çözümümü eklemek istiyorum. Bunu standartla yaptım ed:

ed -s sometextfile <<< $'-2,$d\nwq'

Bu yerinde düzenlemeyi kullanarak son 2 satırları siler (o halde gelmez geçici dosyayı kullanmak /tmp!!)


6

Çok büyük dosyaları gerçekten yerinde kesmek için truncatekomuta sahibiz . Satırları bilmiyor ama tail+ wcsatırları bayta dönüştürebilir:

file=bigone.log
lines=3
truncate -s -$(tail -$lines $file | wc -c) $file

Dosya aynı anda yazılırsa bariz bir yarış durumu vardır. Bu durumda kullanmak daha iyi olabilir head- dosyanın başlangıcından itibaren baytları sayar (zihin diski IO), bu nedenle her zaman satır sınırını keseriz (dosya aktif olarak yazılırsa muhtemelen beklenenden daha fazla satır):

truncate -s $(head -n -$lines $file | wc -c) $file

Oturum açma girişiminde kullanıcı adı yerine şifre girmeyi başaramazsanız, kullanışlı tek satırlık:

truncate -s $(head -n -5 /var/log/secure | wc -c) /var/log/secure

4

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

sed ':a;$!N;1,4ba;P;$d;D' file

Güzel. Son kesme işaretini ( ') kaçırdınız .
Thor

çok geç yorum için özür dilerim ama denedim ve (AIX / posix'ime uyarlandı) son satır hariç tümünü yazdırmayı başaramadı. Kesinlikle döngü bir sonraki böylece kod okuma, ben son dört satır kaldırılır anlamıyorum, açık döngü 4 ilk hatları üzerinde d, Dya da PGNU sed ve POSIX sürümüne sahip. Görünüşe göre satırlar Deylemin 'sonuna' geçmeden yeni bir döngü için çalışma arabelleğinde tutulur .
NeronLeVelu

@NeronLeVelu program desen uzayına 4 satırlık bir pencerede okur ve ardından bir sonraki satırı ekler ve kalan satırları sildiği dosyanın sonuna gelene kadar ilk satırı yazdırır.
Potong

@potong evet, bir GNU sed üzerinde test ediyorum Dve ters etkiyi yaptıktan sonra posix'in onu boşalttığı satırlar arasında tamponu tutuyorum .
NeronLeVelu

4

Yukarıdaki cevapların çoğu GNU komutları / uzantıları gerektiriyor gibi görünüyor:

    $ head -n -2 myfile.txt
    -2: Badly formed number

Biraz daha taşınabilir bir çözüm için:

     perl -ne 'push(@fifo,$_);print shift(@fifo) if @fifo > 10;'

VEYA

     perl -ne 'push(@buf,$_);END{print @buf[0 ... $#buf-10]}'

VEYA

     awk '{buf[NR-1]=$0;}END{ for ( i=0; i < (NR-10); i++){ print buf[i];} }'

"10", "n" nerede.


2

Buradaki cevaplarla, sed'in bu uygulama için en iyi araç olmadığını zaten öğrenmişsinizdir.

Ancak bunu sed kullanarak yapmanın bir yolu olduğunu düşünüyorum; fikir, EOF'ye basmadan okuyana kadar boşluk tutmak için N satır eklemektir. EOF vurulduğunda, bekletme alanının içeriğini yazdırın ve çıkın.

sed -e '$!{N;N;N;N;N;N;H;}' -e x

Yukarıdaki sed komutu son 5 satırı atlayacaktır.


2

Aşağıdaki komutu deneyin:

n = line number
tail -r file_name | sed '1,nd' | tail -r

Lütfen bunun nasıl çalıştığını açıklayın. Bilginize - kabuk değişkenlerini başlatmak için etrafta boşluk bırakmamalıyız =.
codeforester

@codeforester İlk satır sanırım bir yorumdu. Yalnızca tail -rbaşkalarının tacsatır sırasını tersine çevirmek için kullandığı yerleri kullanır ve son nsatırları nilk satırlar haline getirir .
Nicolas Melay

2

3 adımda yapılabilir:

a) Düzenlemek istediğiniz dosyadaki satırların sayısını sayın:

 n=`cat myfile |wc -l`

b) Bu sayıdan silinecek satır sayısını çıkarın:

 x=$((n-3))

c) sed'e bu satır numarasından ( $x) sonuna kadar silmesini söyleyin :

 sed "$x,\$d" myfile

Kötü matematik. Eğer 3 satırı silmeniz gerekiyorsa, 3'ü çıkarın ama 1'i çıkarın. Matematiğinizle, dosyada 10 satır varsa, 10 - 3 = 7 ve sed7'den 10'a kadar olan satırları silmek için kullanıyorsanız , yani 3 değil 4 satır silmek için kullanıyorsanız
mathguy

1

İle toplam satır sayısını alabilir wc -l <file>ve kullanabilirsiniz

head -n <total lines - lines to remove> <file>


1

Bu, son 3 satırı şunlardan kaldıracaktır file:

for i in $(seq 1 3); do sed -i '$d' file; done;


1
Bu, büyük dosyalar için çok pahalıdır - tüm dosyanın n defa okunması ve yeniden yazılması gerekir! Ve bir o kadar çatal sed.
codeforester

bu en etkili çözüm olmasa da, en basit ve anlaşılması kolay çözümdür
Dharam

0

Bu çözümü tercih ediyorum;

head -$(gcalctool -s $(cat file | wc -l)-N) file

burada N , kaldırılacak satır sayısıdır.


0
sed -n ':pre
1,4 {N;b pre
    }
:cycle
$!{P;N;D;b cycle
  }' YourFile

Posix versiyonu


0

Son 4 satırı silmek için:

$ nl -b a file | sort -k1,1nr | sed '1, 4 d' | sort -k1,1n | sed 's/^ *[0-9]*\t//'   

biraz ağır (özellikle kaynaklarda) bir kafaya kıyasla. En azından tac file | sed '1,4d' | tacsıralama, daha sonra önek maliyetini çok kaynakların kaldırması nedeniyle.
NeronLeVelu

@NeronLeVelu haklısınız ama tackomut yok bazı sistemler (örneğin FreeBSD?)
mstafreshi

0

Bunu buldum, burada n silmek istediğiniz satır sayısıdır:

count=`wc -l file`
lines=`expr "$count" - n`
head -n "$lines" file > temp.txt
mv temp.txt file
rm -f temp.txt

Biraz dolambaçlı ama bence takip etmesi kolay.

  1. Ana dosyadaki satır sayısını sayın
  2. Sayımdan çıkarmak istediğiniz satır sayısını çıkarın
  3. Saklamak ve geçici bir dosyada saklamak istediğiniz satır sayısını yazdırın
  4. Ana dosyayı geçici dosya ile değiştirin
  5. Geçici dosyayı kaldırın

0

Bir dosyanın son N satırını silmek için, aynı konsepti kullanabilirsiniz.

$ sed '2,4d' file

Dosyayı ters çevirmek için tail komutlu bir combo kullanabilirsiniz: eğer N 5 ise

$ tail -r file | sed '1,5d' file | tail -r > file

Ve bu yol, head -n -5 filekomutun çalışmadığı yerlerde de çalışır (bir mac'ta olduğu gibi!).


0

Docker'da bu benim için çalıştı:

head --lines=-N file_path >> file_path

-2

Bu son 12 satırı kaldıracak

sed -n -e :a -e '1,10!{P;N;D;};N;ba'

1
Biraz açıklama lütfen yardımcı olur.
IpsRich
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.