Saya memiliki beberapa file yang ingin saya hapus baris baru terakhir jika itu adalah karakter terakhir dalam file. od -c
memperlihatkan kepada saya bahwa perintah yang saya jalankan tidak menulis file dengan baris baru yang tertinggal:
0013600 n t > \n
Saya sudah mencoba beberapa trik dengan sed tetapi yang terbaik yang bisa saya pikirkan adalah tidak melakukan trik:
sed -e '$s/\(.*\)\n$/\1/' abc
Ada ide bagaimana melakukan ini?
\n
, di linux adalah satu karakterJawaban:
atau, untuk mengedit file di tempat:
[Catatan Editor:
-pi -e
pada awalnya-pie
, tetapi, sebagaimana dicatat oleh beberapa komentator dan dijelaskan oleh @hvd, yang terakhir tidak berfungsi.]Ini digambarkan sebagai 'penghujatan perl' di situs web awk yang saya lihat.
Tapi, dalam ujian, itu berhasil.
sumber
chomp
. Dan itu mengalahkan menghirup file.perl -pi -e 'chomp if eof' filename
, untuk mengedit file di tempat alih-alih membuat file sementaraperl -pie 'chomp if eof' filename
-> Tidak dapat membuka skrip perl "chomp if eof": Tidak ada file atau direktori;perl -pi -e 'chomp if eof' filename
-> worksAnda dapat memanfaatkan fakta bahwa pergantian perintah shell menghapus karakter baris baru :
Bentuk sederhana yang bekerja di bash, ksh, zsh:
Alternatif portable (POSIX-compliant) (sedikit kurang efisien):
catatan:
in.txt
ujung dengan beberapa karakter baris baru, substitusi perintah menghapus semua dari mereka - terima kasih, @Sparhawk. (Itu tidak menghapus karakter spasi selain dari mengikuti baris baru.)printf %s
memastikan bahwa tidak ada baris baru yang ditambahkan ke output (itu adalah alternatif yang sesuai dengan POSIX untuk yang tidak standarecho -n
; lihat http://pubs.opengroup.org/onlinepubs/009696799/utilities/echo.html dan https: //unix.stackexchange. com / a / 65819 )Sebuah panduan untuk jawaban yang lain :
Jika Perl tersedia, cari jawaban yang diterima - sederhana dan hemat memori (tidak membaca seluruh file input sekaligus).
Jika tidak, pertimbangkan ghostdog74 ini AWK jawaban - itu jelas, tetapi juga hemat memori ; a lebih mudah dibaca setara (POSIX-compliant) adalah:
awk 'NR > 1 { print prev } { prev=$0 } END { ORS=""; print }' in.txt
END
blok, di mana ia dicetak tanpa\n
jejak karena pengaturan pemisah catatan keluaran (OFS
) ke string kosong.Jika Anda menginginkan solusi verbose, tetapi cepat dan tangguh yang benar - benar diedit di tempat (sebagai lawan membuat temp. File yang kemudian menggantikan yang asli), pertimbangkan skrip Perl jrockway .
sumber
Anda dapat melakukan ini dengan
head
dari GNU coreutils, ia mendukung argumen yang relatif terhadap akhir file. Jadi untuk meninggalkan penggunaan byte terakhir:Untuk menguji baris akhir yang berakhir, Anda dapat menggunakan
tail
danwc
. Contoh berikut menyimpan hasil ke file sementara dan selanjutnya menimpa yang asli:Anda juga dapat menggunakan
sponge
dari mulaimoreutils
mengedit "di tempat":Anda juga dapat membuat fungsi yang dapat digunakan kembali secara umum dengan memasukkan ini di
.bashrc
file Anda :Memperbarui
Seperti dicatat oleh KarlWilbur dalam komentar dan digunakan dalam jawaban Sorentar ,
truncate --size=-1
dapat menggantikanhead -c-1
dan mendukung pengeditan di tempat.sumber
truncate --size=-1
daripadahead -c -1
hanya mengubah ukuran file input daripada membaca di file input, menuliskannya ke file lain, lalu mengganti yang asli dengan file output.head -c -1
akan menghapus karakter terakhir terlepas dari apakah itu baris baru atau tidak, itu sebabnya Anda harus memeriksa apakah karakter terakhir adalah baris baru sebelum Anda menghapusnya.Edit 2:Berikut ini adalahawk
versi (dikoreksi) yang tidak mengumpulkan array yang berpotensi besar:awk '{if (line) line print; line = $ 0} END {printf $ 0} 'abcsumber
awk
versi Anda . Dibutuhkan dua offset (dan tes yang berbeda) dan saya hanya menggunakan satu. Namun, Anda bisa menggunakanprintf
bukanORS
.head -n -1 abc | cat <(tail -n 1 abc | tr -d '\n') | ...
melongo
sumber
awk '{ prev_line = line; line = $0; } NR > 1 { print prev_line; } END { ORS = ""; print line; }' file
ini seharusnya lebih mudah dibaca.awk 'NR>1 {print p} {p=$0} END {printf $0}' file
.printf
adalah argumen format . Jadi jika file input memiliki sesuatu yang dapat diartikan sebagai penentu format seperti%d
, Anda akan mendapatkan kesalahan. Perbaikan akan mengubahnya keprintf "%s" $0
Metode yang sangat sederhana untuk file single-line, membutuhkan gema GNU dari coreutils:
sumber
\n
hadir. Saat dikonversi ke baris baru.$(...)
dikutip/bin/echo -n "$(cat infile)"
Juga, saya tidak yakin apa maks lenecho
atau shell akan melintasi os / versi shell / distro (saya hanya googling ini & itu adalah lubang kelinci), jadi saya tidak yakin seberapa portabel (atau performer) itu sebenarnya untuk apa pun selain file kecil - tetapi untuk file kecil, hebat.Jika Anda ingin melakukannya dengan benar, Anda perlu sesuatu seperti ini:
Kami membuka file untuk membaca dan menambahkan; membuka untuk menambahkan berarti kita sudah
seek
mengedit sampai akhir file. Kami kemudian mendapatkan posisi numerik dari akhir filetell
. Kami menggunakan angka itu untuk mencari kembali satu karakter, dan kemudian kami membaca satu karakter itu. Jika itu adalah baris baru, kami memotong file ke karakter sebelum baris baru itu, jika tidak, kami tidak melakukan apa-apa.Ini berjalan dalam waktu dan ruang konstan untuk input apa pun, dan juga tidak memerlukan ruang disk lagi.
sumber
Ini adalah solusi Python yang bagus dan rapi. Saya tidak berusaha untuk singkat di sini.
Ini memodifikasi file di tempat, daripada membuat salinan file dan menghapus baris baru dari baris terakhir salinan. Jika file berukuran besar, ini akan jauh lebih cepat daripada solusi Perl yang dipilih sebagai jawaban terbaik.
Ini memotong file dengan dua byte jika dua byte terakhir adalah CR / LF, atau satu byte jika byte terakhir adalah LF. Itu tidak berusaha untuk memodifikasi file jika byte terakhir tidak (CR) LF. Ini menangani kesalahan. Diuji dalam Python 2.6.
Masukkan ini dalam file yang disebut "striplast" dan
chmod +x striplast
.PS Dalam semangat "Perl golf", inilah solusi Python terpendek saya. Ini menghirup seluruh file dari input standar ke dalam memori, menghapus semua baris baru pada akhirnya, dan menulis hasilnya ke output standar. Tidak sesingkat Perl; Anda tidak bisa mengalahkan Perl untuk hal-hal kecil yang rumit dan cepat seperti ini.
Hapus "\ n" dari panggilan ke
.rstrip()
dan itu akan menghapus semua ruang putih dari akhir file, termasuk beberapa baris kosong.Masukkan ini ke dalam "slurp_and_chomp.py" dan kemudian jalankan
python slurp_and_chomp.py < inputfile > outputfile
.sumber
Solusi cepat menggunakan utilitas gnu
truncate
:Tes akan benar jika file tersebut memang memiliki garis baru.
Penghapusannya sangat cepat, benar-benar di tempat, tidak ada file baru yang diperlukan dan pencarian juga membaca dari ujung hanya satu byte (
tail -c1
).sumber
[ -z $(tail -c1 filename) ] && truncate -s -1 filename
(juga, dalam membalas komentar lain,truncate
perintah tidak bekerja dengan stdin, nama file diperlukan)Satu lagi perl WTDI:
sumber
Lihat juga Cocokkan karakter apa saja (termasuk baris baru) di sed .
sumber
tr -d '\n'
Menggunakan dd:
sumber
sumber
g
atau tanda kurung di sekitareof
:perl -pi -e 's/\n$// if eof' your_file
.Dengan asumsi jenis file Unix dan Anda hanya ingin baris baru terakhir ini berfungsi.
Itu tidak akan berfungsi pada banyak baris baru ...
* Hanya berfungsi jika baris terakhir adalah baris kosong.
sumber
sed
solusi yang berfungsi bahkan untuk baris terakhir yang tidak kosong: stackoverflow.com/a/52047796Namun jawaban lain FTR (dan favorit saya!): Gema / hal yang Anda ingin strip dan menangkap output melalui backticks. Baris baru terakhir akan dilucuti. Sebagai contoh:
sumber
POSIX SED:
'$ {/ ^ $ / d}'
sumber
echo -en 'a\nb\n' | sed '${/^$/d}'
tidak akan menghapus apa pun.echo -en 'a\nb\n\n' | sed '${/^$/d}'
akan dihapus karena seluruh baris terakhir kosong.Ini adalah solusi yang baik jika Anda membutuhkannya untuk bekerja dengan pipa / redirection alih-alih membaca / output dari atau ke file. Ini bekerja dengan satu atau beberapa baris. Ini berfungsi apakah ada baris tambahan atau tidak.
Detail:
head -c -1
memotong karakter terakhir dari string, terlepas dari apa karakternya. Jadi jika string tidak diakhiri dengan baris baru, maka Anda akan kehilangan karakter.sed '$s/$//'
. Yang pertama$
berarti hanya menerapkan perintah ke baris terakhir.s/$//
berarti mengganti "ujung garis" dengan "tidak ada", yang pada dasarnya tidak melakukan apa-apa. Tetapi ini memiliki efek samping menambahkan baris baru setelah tidak ada.Catatan: Default Mac
head
tidak mendukung-c
opsi. Anda bisa melakukannyabrew install coreutils
dan menggunakannyaghead
.sumber
Satu-satunya waktu saya ingin melakukan ini adalah untuk kode golf, dan kemudian saya baru saja menyalin kode saya keluar dari file dan menempelkannya ke dalam
echo -n 'content'>file
pernyataan.sumber
sumber
Saya memiliki masalah yang sama, tetapi bekerja dengan file windows dan perlu menjaga CRLF - solusi saya di linux:
sumber
Seharusnya menghapus kejadian terakhir dari \ n dalam file. Tidak berfungsi pada file besar (karena keterbatasan buffer sed)
sumber
rubi:
atau:
sumber