tambahkan teks dengan gema tanpa baris baru

14

Saya ingin menambahkan teks ke file suka echo "abc" >>file.txt.

Tapi ini tambahkan abcsetelah baris baru

Bagaimana saya bisa menambahkan abcdi akhir file dengan gema tanpa baris baru?

choijj
sumber
2
File sudah memiliki baris baru, Anda tinggal menambahkan setelahnya. Jadi, Anda harus mengganti karakter baris baru dari baris terakhir, dengan "abc".
ctrl-alt-delor
Selamat datang di StackExchange! Pertanyaan Anda bagus; akan lebih baik jika Anda menentukan contoh konten file Anda (sebelum penambahan, apa yang Anda dapatkan setelah penambahan, apa yang Anda inginkan). Saya mengatakan ini karena salah satu jawabannya adalah bagaimana menambahkan abctanpa baris baru akhir, yang (setelah membaca pertanyaan Anda dengan penuh perhatian) tampaknya tidak seperti yang Anda inginkan.
Law29

Jawaban:

19

echo "abc" >>file.txtmenempatkan baris baru setelahnya abc , bukan sebelumnya. Jika Anda berakhir dengan abcbarisnya sendiri, itu berarti baris baru sebelumnya abcsudah ada di file.txt.

Perhatikan bahwa sangat normal bagi file teks untuk mengakhiri baris baru. Pada unix, baris terdiri dari urutan karakter selain null⁰ atau baris baru diikuti oleh baris baru. 1 Oleh karena itu file teks yang tidak kosong diakhiri dengan karakter baris baru.

Jika Anda ingin menambahkan teks ke baris terakhir file, maka Anda tidak dapat melakukannya dengan >>, karena ini selalu ditambahkan ke file, jadi selalu menulis setelah baris baru terakhir. Sebagai gantinya Anda membutuhkan alat yang mampu memodifikasi file yang ada. Misalnya, Anda dapat menggunakan sed :

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

Dalam perintah sed, yang pertama $berarti "lakukan perintah berikut hanya di baris terakhir", perintah itu s/REGEX/REPLACEMENT/menggantikan REGEX dengan REPLACEMENT, dan persamaan reguler $cocok di akhir baris.

Perintah sed Linux memiliki fitur bawaan untuk mengotomatiskan urutan buat-file-dan-ganti baru ini, sehingga Anda dapat mempersingkatnya menjadi

sed -i '$ s/$/abc/' file.txt

Itu byte nol, yang panggilan ASCII NUL dan panggilan Unicode U + 0000. Program pemrosesan teks mungkin atau mungkin tidak mengatasi karakter ini.
1 Lihat definisi File Teks , Baris , dan Karakter Baris Baru di bagian "Definisi" pada bab Definisi Dasar dari IEEE 1003.1-2008: 2016.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Apakah paragraf kedua Anda dimaksudkan untuk menyiratkan bahwa file yang tidak berakhir dengan baris baru bukan file teks? Misalnya jika saya mengambil file teks ASCII yang sudah ada yang diakhiri dengan baris baru dan menambahkan satu byte 0x41(ASCII 'A'), secara teknis tidak lagi file teks? Jika demikian, saya sarankan menekankan hal itu karena itu semacam definisi yang tidak intuitif; jika tidak, sedikit perubahan pada kata-kata dapat membantu menghindari kebingungan.
David Z
2
@ DavidZ: Itu adalah definisi standar dari file teks di Unixland. IIRC bahkan di POSIX di suatu tempat.
Kevin
1
@ Kevin Menarik, saya belum pernah mendengar itu sebelumnya. Yah, meskipun standar, saya pikir itu agak tidak intuitif.
David Z
15

Saya tidak berpikir itu mungkin dengan echoperintah, gunakan sedpendekatan berikut sebagai gantinya:

sed -i '$ s/$/abc/' file.txt
  • -i- memodifikasi file inplace
  • $ - menunjukkan catatan / baris terakhir
  • s/$/abc/- gantikan akhir baris $dengan substring abc(untuk catatan terakhir)
RomanPerekhrest
sumber
2
Perhatikan bahwa "di tempat" tidak benar-benar berarti di tempat. Ini berarti "menulis konten yang diedit ke file bernama sementara di samping file yang ada dan kemudian menggantinya". Anda dapat membuktikan ini dengan melihat inode dengandate >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima
@roaima, saya sadar tentang perubahan nomor inode.
RomanPerekhrest
2
Saya pikir Anda akan melakukannya, tetapi saya khawatir bahwa dengan penekanan Anda di tempat OP malam pikir itu bisa digunakan untuk menghindari penggunaan ruang disk ganda, misalnya dengan file besar.
roaima
@roaima, pikir malam -> mungkin berpikir ...
RomanPerekhrest
13

Dengan asumsi bahwa file tersebut belum berakhir di baris baru dan Anda hanya ingin menambahkan beberapa teks tanpa menambahkannya, Anda dapat menggunakan -nargumen, misalnya

echo -n "some text here" >> file.txt

Namun, beberapa sistem UNIX tidak menyediakan opsi ini; jika itu yang dapat Anda gunakan printf, mis

printf %s "some text here" >> file.txt

( %sargumen awal adalah untuk menjaga terhadap teks tambahan yang %memformat karakter di dalamnya)

Dari man echo(di macOS High Sierra):

-n

Jangan cetak karakter baris baru yang tertinggal. Ini juga dapat dicapai dengan menambahkan '\c'ke akhir string, seperti yang dilakukan oleh sistem yang kompatibel dengan iBCS2. Perhatikan bahwa opsi ini dan juga efek '\c'implementasi didefinisikan dalam IEEE Std 1003.1-2001 ("POSIX.1") sebagaimana telah diubah oleh Cor. 1-2002. Aplikasi yang bertujuan untuk portabilitas maksimum sangat disarankan untuk digunakan printf(1)untuk menekan karakter baris baru.

halus
sumber
Ini cukup jelas tidak berakhir dengan baris baru. echo -ntidak akan menempatkan baris baru di akhir abc, tetapi abcmasih akan didahului oleh baris baru, yang ingin dihindari oleh pengguna.
Kusalananda
@ Kusalananda Jawaban saya lebih menggunakan asumsi bahwa OP akan mencoba mengubah proses mereka sehingga palsu \ntidak muncul di tempat pertama. Lebih banyak opsi lebih baik, terutama ketika mereka tidak perlu menulis ulang seluruh file setiap kali terjadi perubahan (yang bisa agak lambat dan berjalan dalam waktu polinomial jika dilakukan berulang kali).
lembut
9

Jika Anda memiliki truncateperintah dan file teks Anda memiliki NL sebagai karakter terakhir, Anda dapat menghapusnya dan kemudian menambahkan teks Anda seperti ini:

truncate --size -1 file.txt
echo "abc" >>file.txt

(Perhatikan bahwa truncatetidak ada yang peduli dengan konten file, dan dalam contoh ini cukup kurangi ukuran file dengan satu byte. Jika karakter terakhir Anda bukan satu byte, yaitu karakter multi-byte "lebar" maka Anda akan memperkenalkan korupsi.)

roaima
sumber
5

Yang Anda inginkan adalah menambahkannya di akhir baris terakhir, jadi sebelum pembatas baris terakhir, jadi tepat sebelum karakter terakhir file.

Dengan ksh93, Anda dapat melakukan:

echo abc 1<> file >#((EOF - 1))

Di mana 1<>operator standar untuk membuka file dalam mode baca + tulis (dan yang lebih penting tanpa pemotongan ) pada stdout dan >#((...))merupakan operator pencarian khusus ksh93 (di sini untuk mencari sebelum byte terakhir). Catatan yang echomenulis di abc<newline>mana amenimpa baris baru yang ada di sana dan echomenambahkan baris baru sendiri.

The zshsetara:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

Meskipun untuk padanan yang lebih tepat, Anda juga perlu mencetak pesan kesalahan saat gagal mencari:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file
Stéphane Chazelas
sumber
-1

Mungkin UUOC tetapi Anda juga bisa melakukan:

echo "$(cat file.txt)abc" >file.txt

Seperti yang ditunjukkan Gilles, perintah ini terbatas:

Ini sebagian besar berfungsi, tetapi tidak jika kadang-kadang ada baris kosong di akhir file dan baris kosong sebelumnya. Misalnya file dengan jumlah baris tetap, di mana baris terakhir awalnya kosong dan diperpanjang dari waktu ke waktu, dan baris berikutnya-ke-terakhir terkadang kosong.

Selain itu berhati-hatilah dalam menggunakan catfile yang tidak Anda kenal:

Kesimpulan :

Gunakan sed

jesse_b
sumber
2
Ini sebagian besar berfungsi, tetapi tidak jika kadang-kadang ada baris kosong di akhir file dan baris kosong sebelumnya. Misalnya file dengan jumlah baris tetap, di mana baris terakhir awalnya kosong dan diperpanjang dari waktu ke waktu, dan baris berikutnya-ke-terakhir terkadang kosong.
Gilles 'SANGAT berhenti menjadi jahat'
Haruskah saya menghapusnya? Saya pasti berpikir Roman / jawaban Anda adalah cara yang tepat untuk pergi tetapi saya tahu saya pribadi suka melihat alternatif, dan OP memang meminta echo: p
jesse_b
1
Ini juga menempatkan seluruh file pada baris perintah
n.caillou
@ n.caillou ya? Ini tidak akan mencetak apa pun untuk STDOUT.
jesse_b
2
Ya, tidak satu pun dari kerentanan itu yang benar-benar terkait cat, tetapi untuk masalah dengan urutan pelarian sewenang-wenang yang dikirim ke terminal.
ilkkachu