Son satırı Bash'teki bir dosyadan kaldır


Yanıtlar:


408

Kullanma GNU sed:

sed -i '$ d' foo.txt

-iSeçenek mevcut değildir GNU sedGeçici dosya ile bir süzgeç olarak kullanmak zorunda, 3.95 den eski sürümleri:

cp foo.txt foo.txt.tmp
sed '$ d' foo.txt.tmp > foo.txt
rm -f foo.txt.tmp

Tabii ki, bu durumda da kullanabilirsiniz head -n -1yerine sed.

Mac os işletim sistemi:

Mac OS X'te (10.7.4 itibariyle), sed -iyukarıdaki komutun eşdeğeri

sed -i '' -e '$ d' foo.txt

56
Mac OS X'te (10.7.4'ten itibaren), sed -iyukarıdaki komutun karşılığıdır sed -i '' -e '$ d' foo.txt. Ayrıca, head -n -1şu anda Mac'te çalışmaz.
mklement0

26
'$ D' normal ifadesinin ne yaptığını açıklayabilir misiniz? Son satırı kaldırmakla ilgili bir soru, bu yüzden bu soruyu görüntüleyen herkes için en önemli kısım olduğunu düşünüyorum. Teşekkürler :)
kravemir

38
@Miro: Hiçbir şekilde $ dbir normal ifade değildir. Bu bir sed komutudur. dsatır silme komutudur, $"dosyadaki son satır" anlamına gelir. Bir komuttan önce bir konum belirtirken (sed lingo'da "aralık" olarak adlandırılır), bu komut yalnızca belirtilen konuma uygulanır. Yani, bu komut açıkça "bir dosyadaki son satırın aralığında, silin" diyor. Bana sorarsanız, oldukça kaygan ve doğrudan noktaya.
Daniel Kamil Kozar

1
Son satırı ancak boş bir satırsa nasıl kaldırırsınız?
skan

1
@Alex: GNU sed için güncellendi; çeşitli BSD / UNIX / MacOS sed sürümleri hakkında hiçbir fikrim yok ...
thkala

279

Bu, özellikle büyük dosyalarda açık ara en hızlı ve en basit çözümdür:

head -n -1 foo.txt > temp.txt ; mv temp.txt foo.txt

üst satırı silmek istiyorsanız şunu kullanın:

tail -n +2 foo.txt

yani satır 2'den başlayan çıkış hatları anlamına gelir.

sedDosyanın üstünden veya altından satır silmek için kullanmayın - dosya büyükse çok yavaştır.


16
head -n -1 foo.txtyeterli
ДМИТРИЙ МАЛИКОВ

20
head -n -1 bdsutils'in kafasında çalışmaz. en azından macos kullanıyor sürümünde, bu yüzden bu işe yaramaz.
johannes_lalala

23
@johannes_lalala Mac'te brew install coreutils(GNU çekirdek yardımcı programları) gheadyerine kullanabilirsiniz head.
ilginçtir10

Aşağıda, silmek için altta farklı sayıda satır içeren birden fazla dosya olması durumunda otomatikleştiren basit bir bash betiği vardır: cat TAILfixer FILE=$1; TAIL=$2; head -n -${TAIL} ${FILE} > temp ; mv temp ${FILE}Örneğin, dosyamdan 4 satırı silmek için çalıştırın: ./TAILfixer myfile 4tabii ki önce tarafından çalıştırılabilir chmod +x TAILfixer
kılın

Yaşasın çünkü işe yaradı, ama tüm karşılaştırma için sed, bu komut da oldukça yavaştır
Jeff Diederiks

121

BÜYÜK bir dosya (~ 300Gb) ile çalışıyordu ve çözümlerin hiçbiri ölçekli çünkü burada tüm cevapları ile sorun vardı. İşte benim çözümüm:

dd if=/dev/null of=<filename> bs=1 seek=$(echo $(stat --format=%s <filename> ) - $( tail -n1 <filename> | wc -c) | bc )

Kelimeyle: Sonlandırmak istediğiniz dosyanın uzunluğunu bulun (dosya uzunluğu eksi son satırının uzunluğu, kullanarak bc) ve bu konumu dosyanın sonu olarak ayarlayın dd( /dev/nullüzerine bir bayt girerek) o).

Bunun nedeni hızlı tailbaşlar ucundan okuma ve dddosyanın üzerine olacaktır yerde diğer çözümleri şey bu dosyada, her satırını kopyası (ve parse) ziyade.

NOT: Bu, satırı yerinde dosyadan kaldırır! Kendi dosyanızda denemeden önce kukla bir dosyayı yedekleyin veya test edin!


3
DD'yi bile bilmiyordum. Bu en iyi cevap olmalı. Çok teşekkür ederim! Çözüm, gzip edilmiş dosyalar için (blok) çalışmayan bir utanç.
tommy.carstensen

4
Çok, çok akıllı bir yaklaşım! Sadece bir not: gerçek bir dosya gerektirir ve çalışır, bu yüzden borularda, komut ikamelerinde, yönlendirmelerde ve bu tür zincirlerde kullanılamaz.
MestreLion

3
Bu en iyi cevap olmalı. ~ 8 GB dosyam için anında çalıştı.
Peter Cogan

8
mac kullanıcıları: dd if = / dev / null / = <filename> bs = 1 seek = $ (echo $ (stat -f =% z <filename> | cut -c 2-) - $ (kuyruk -n1 <filename> | wc -c) | bc)
Igor

2
Bu yaklaşım büyük dosyalar için bir yoldur!
thomas.han

61

Bir dosyadan son satırı kaldırmak için tüm dosyayı okuma ya da bir şey yeniden yazmadan , kullanabilirsiniz

tail -n 1 "$file" | wc -c | xargs -I {} truncate "$file" -s -{}

Son satırı kaldırmak ve stdout'ta ("pop") yazdırmak için, bu komutu aşağıdakilerle birleştirebilirsiniz tee:

tail -n 1 "$file" | tee >(wc -c | xargs -I {} truncate "$file" -s -{})

Bu komutlar çok büyük bir dosyayı verimli bir şekilde işleyebilir. Bu, Yossi'nin cevabına benzer ve ilham kaynağıdır, ancak birkaç ekstra işlev kullanmaktan kaçınır.

Bunları tekrar tekrar kullanacaksanız ve hata işleme ve diğer bazı özellikleri istiyorsanız, buradaki poptailkomutu kullanabilirsiniz : https://github.com/donm/evenmoreutils


3
Hızlı not: truncateOS X'te varsayılan olarak yoktur. Ancak Brew: kullanarak kurulumu kolaydır brew install truncate.
Guillaume Boudreau

3
Çok hoş. DD olmadan çok daha iyi. Ben tek bir yanlış rakam veya harf felaket büyü olabilir dd kullanmaktan dehşete oldu .. +1
Yossi Farjoun

1
(ŞAKA UYARI) Aslında, ("dd" -> "felaket") 1 değiştirme ve 6 yerleştirme gerektirir; neredeyse "tek yanlış yerleştirilmiş bir rakam veya harf". :)
Kyle

29

Mac Kullanıcıları

yalnızca dosyanın son değiştirilmeden son satırın silinmesini istiyorsanız

sed -e '$ d' foo.txt

giriş dosyasının son satırını silmek istiyorsanız

sed -i '' -e '$ d' foo.txt


Bu benim için çalışıyor ama anlamıyorum. her neyse, işe yaradı.
Melvin

Bayrak -i '', sed'e dosyayı yerinde değiştirmesini söylerken, parametre olarak sağlanan uzantıya sahip bir dosyada yedek tutar. Parametre boş bir dize olduğundan yedekleme dosyası oluşturulmaz. -esed'e bir komut yürütmesini söyler. Komut şu $ danlama gelir: son satırı ( $) bulun ve silin ( d).
Krzysztof Szafranek

24

Mac Kullanıcıları için:

Mac'te, kafa -n -1 çalışmaz. Ve sadece "kafa" ve / veya "kuyruk" komutlarını kullanarak bu sorunu çözmek için [işlem süresi hakkında endişelenmeden] basit bir çözüm bulmaya çalışıyordum.

Aşağıdaki komut dizisini denedim ve sadece "tail" komutunu [Mac'te bulunan seçeneklerle] kullanarak çözebildiğim için mutlu oldum. Yani, Mac'teyseniz ve bu sorunu çözmek için yalnızca "kuyruk" kullanmak istiyorsanız, bu komutu kullanabilirsiniz:

cat dosyası.txt | kuyruk -r | kuyruk -n +2 | kuyruk -r

Açıklama:

1> tail -r: sadece girişindeki satırların sırasını tersine çevirir

2> tail -n +2: bu, girişindeki ikinci satırdan başlayarak tüm satırları yazdırır


2
Homebrew kullanarak coreutils kurmak, GNU kafasını 'ghead' olarak verir, bunu yapmanıza izin verirghead -n -1
biraz

13
echo -e '$d\nw\nq'| ed foo.txt

2
, Kullanımı yerinde dosyasını düzenlemek olmayan bir filtre çözüm için sed '$d'.
lhf

8
awk 'NR>1{print buf}{buf = $0}'

Esasen, bu kod şunları söylüyor:

İlk satırdan sonraki her satır için arabelleğe alınmış satırı yazdırın

her satır için arabelleği sıfırlayın

Arabellek bir satır gecikmeli, böylece 1'den n-1'e kadar olan satırları yazdırırsınız


2
Bu çözüm bir filtredir ve dosyayı yerinde düzenlemez.
lhf


0

Bu çözümlerin her ikisi de başka şekillerde. Bunları biraz daha pratik, açık ve kullanışlı buldum:

Dd kullanma:

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
dd if=${ORIGINALFILE} of=${ORIGINALFILE}.tmp status=none bs=1 count=$(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc )
/bin/mv -f ${ORIGINALFILE}.tmp ${ORIGINALFILE}

Kesme kullanma:

BADLINESCOUNT=1
ORIGINALFILE=/tmp/whatever
truncate -s $(printf "$(stat --format=%s ${ORIGINALFILE}) - $(tail -n${BADLINESCOUNT} ${ORIGINALFILE} | wc -c)\n" | bc ) ${ORIGINALFILE}

Ahh. Çok karmaşık.
Robert

0

Linux

$ son satır, d silmek için:

sed '$d' ~/path/to/your/file/name

Mac os işletim sistemi

Sed -i eşdeğeri

sed -i '' -e '$ d' ~/path/to/your/file/name

0

El ile nasıl yapabilirsiniz (hızlı bir şekilde bir dosyadaki son satırı kaldırmak gerektiğinde ben şahsen bu yöntemi çok kullanın):

vim + [FILE]

Buradaki +işaret, dosya vim metin düzenleyicisinde açıldığında, imlecin dosyanın son satırına konumlandırılacağı anlamına gelir.

Şimdi klavyenizde diki kez basın . Bu tam olarak istediğinizi yapar - son satırı kaldırın. Bundan sonra basın :tarafından takip xve sonra basın Enter. Bu değişiklikleri kaydedecek ve sizi kabuğa geri getirecektir. Şimdi, son satır başarıyla kaldırıldı.


2
Vurgu basitlik burada kayboldu
Peter bana M

-4

Yakut (1.9+)

ruby -ne 'BEGIN{prv=""};print prv ; prv=$_;' file
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.