Saya memiliki file yang diakhiri dengan satu atau lebih baris baru dan harus berakhir hanya dalam satu baris baru. Bagaimana saya bisa melakukannya dengan alat Bash / Unix / GNU?
Contoh file buruk:
1\n
\n
2\n
\n
\n
3\n
\n
\n
\n
Contoh file yang diperbaiki:
1\n
\n
2\n
\n
\n
3\n
Dengan kata lain: Harus ada tepat satu baris baru antara EOF dan karakter non-baris terakhir file.
Implementasi Referensi
Baca konten file, potong satu baris baru sampai tidak ada dua baris lagi di akhir, tulis kembali:
#! /bin/python
import sys
with open(sys.argv[1]) as infile:
lines = infile.read()
while lines.endswith("\n\n"):
lines = lines[:-1]
with open(sys.argv[2], 'w') as outfile:
for line in lines:
outfile.write(line)
Klarifikasi: Tentu saja, perpipaan diperbolehkan, jika itu lebih elegan.
sed
proposal saya hanya berpikir OMG ...awk: illegal statement
.brew install mawk
dan mengubah perintah untukmawk
bekerja.Dari skrip satu-baris yang berguna untuk sed .
sumber
find . -type f -name '*.js' -exec sed --in-place -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \;
find . -type f -name '*.js' -exec sed -i '' -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \;
Karena Anda sudah memiliki jawaban dengan alat yang lebih cocok, sed and awk; Anda bisa mengambil keuntungan dari kenyataan bahwa
$(< file)
strip off trailing blank.Peretasan murah itu tidak akan berfungsi untuk menghapus jejak kosong yang mungkin mengandung spasi atau karakter non-cetak lainnya, hanya untuk menghapus jejak kosong. Ini juga tidak akan berfungsi jika file berisi null byte.
Dalam shell selain bash dan zsh, gunakan
$(cat file)
sebagai ganti$(<file)
.sumber
$()
membuang baris baru. Itu keputusan desain. Saya berasumsi bahwa ini akan membuat integrasi dalam string lain lebih mudah:echo "On $(date ...) we will meet."
akan menjadi jahat dengan baris baru yang hampir setiap perintah shell menghasilkan di akhir.[[ $a == '' ]] || printf '%s\n' "$a" >"$file"
.a=$(gtac file.txt); printf '%s\n' "$a" | gtac > file.txt
Anda dapat menggunakan trik ini dengan
cat
&printf
:Sebagai contoh
Yang
$
menunjukkan akhir garis.Referensi
sumber
Pertanyaan ini ditandai dengan ed , tetapi tidak ada yang mengusulkan
ed
solusi.Ini dia:
atau, yang setara,
ed
akan menempatkan Anda pada baris terakhir dari buffer pengeditan secara default saat startup.Perintah pertama (
a
) menambahkan baris kosong ke ujung buffer (baris kosong dalam skrip pengeditan adalah baris ini, dan titik (.
) hanya untuk kembali ke mode perintah).Perintah kedua (
?
) mencari baris terdekat sebelumnya yang berisi sesuatu (bahkan karakter spasi putih), dan kemudian menghapus semuanya sampai akhir buffer dari baris berikutnya.Perintah ketiga (
w
) menulis file kembali ke disk.Baris kosong yang ditambahkan melindungi sisa file agar tidak terhapus jika tidak ada baris kosong di akhir file asli.
sumber
Berikut adalah solusi Perl yang tidak memerlukan membaca lebih dari satu baris ke memori sekaligus:
atau, sebagai one-liner:
Ini membaca file satu baris pada satu waktu dan memeriksa setiap baris untuk melihat apakah mengandung karakter non-baris baru. Jika tidak, itu menambah penghitung; jika ya, ia akan mencetak jumlah baris baru yang ditunjukkan oleh penghitung, diikuti oleh baris itu sendiri, dan kemudian mengatur ulang penghitung.
Secara teknis, bahkan buffering satu baris dalam memori tidak perlu; akan mungkin untuk memecahkan masalah ini menggunakan jumlah memori yang konstan dengan membaca file dalam potongan-potongan tetap dan memprosesnya karakter dengan karakter menggunakan mesin negara. Namun, saya menduga itu tidak perlu rumit untuk kasus penggunaan biasa.
sumber
Jika file Anda cukup kecil untuk menghirup memori, Anda dapat menggunakan ini
sumber
Dalam python (saya tahu itu bukan apa yang Anda inginkan, tetapi jauh lebih baik karena dioptimalkan, dan pendahuluan ke versi bash) tanpa menulis ulang file dan tanpa membaca semua file (yang merupakan hal yang baik jika file tersebut adalah sangat besar):
Perhatikan bahwa ini tidak berfungsi pada file di mana karakter EOL bukan '\ n'.
sumber
Versi bash, mengimplementasikan algoritma python, tetapi kurang efisien karena membutuhkan banyak proses:
sumber
Ini cepat untuk mengetik, dan, jika Anda tahu sed, mudah diingat:
Ia menggunakan skrip sed untuk menghapus baris kosong terkemuka dari skrip satu baris berguna untuk sed , dirujuk oleh Alexey, di atas, dan tac (reverse cat).
Dalam tes cepat, pada 18MB, 64.000 file baris, pendekatan Alexey lebih cepat, (0,036 vs 0,046 detik).
sumber