Bir dosya var, foo.txt
şu hatlar içeren:
a
b
c
Varlığının içeriği ile sonuçlanan basit bir komut istiyorum foo.txt
:
a
b
Bir dosya var, foo.txt
şu hatlar içeren:
a
b
c
Varlığının içeriği ile sonuçlanan basit bir komut istiyorum foo.txt
:
a
b
Yanıtlar:
Kullanma GNU sed
:
sed -i '$ d' foo.txt
-i
Seçenek mevcut değildir GNU sed
Geç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 -1
yerine sed
.
Mac os işletim sistemi:
Mac OS X'te (10.7.4 itibariyle), sed -i
yukarıdaki komutun eşdeğeri
sed -i '' -e '$ d' foo.txt
$ d
bir normal ifade değildir. Bu bir sed komutudur. d
satı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.
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.
sed
Dosyanın üstünden veya altından satır silmek için kullanmayın - dosya büyükse çok yavaştır.
head -n -1 foo.txt
yeterli
brew install coreutils
(GNU çekirdek yardımcı programları) ghead
yerine kullanabilirsiniz head
.
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 4
tabii ki önce tarafından çalıştırılabilir chmod +x TAILfixer
sed
, bu komut da oldukça yavaştır
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ı tail
başlar ucundan okuma ve dd
dosyanı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!
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 poptail
komutu kullanabilirsiniz :
https://github.com/donm/evenmoreutils
truncate
OS X'te varsayılan olarak yoktur. Ancak Brew: kullanarak kurulumu kolaydır brew install truncate
.
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
-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. -e
sed'e bir komut yürütmesini söyler. Komut şu $ d
anlama gelir: son satırı ( $
) bulun ve silin ( d
).
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
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
ghead -n -1
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
awk "NR != `wc -l < text.file`" text.file |> text.file
Bu pasaj hile yapar.
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}
sed '$d' ~/path/to/your/file/name
sed -i '' -e '$ d' ~/path/to/your/file/name
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 d
iki kez basın . Bu tam olarak istediğinizi yapar - son satırı kaldırın. Bundan sonra basın :
tarafından takip x
ve 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ı.
sed -i
yukarıdaki komutun karşılığıdırsed -i '' -e '$ d' foo.txt
. Ayrıca,head -n -1
şu anda Mac'te çalışmaz.