Ini mungkin solusi yang kompleks .
Saya mencari operator sederhana seperti ">>", tetapi untuk membuat prapengisian.
Saya khawatir itu tidak ada. Saya harus melakukan sesuatu seperti
mv myfile tmp cat myheader tmp> myfile
Adakah yang lebih pintar?
Ini mungkin solusi yang kompleks .
Saya mencari operator sederhana seperti ">>", tetapi untuk membuat prapengisian.
Saya khawatir itu tidak ada. Saya harus melakukan sesuatu seperti
mv myfile tmp cat myheader tmp> myfile
Adakah yang lebih pintar?
mktemp
? Anda selalu dapat membersihkan file temp setelahnya ...Jawaban:
The hack di bawah ini adalah jawaban yang off-the-manset cepat yang bekerja dan menerima banyak upvotes. Kemudian, ketika pertanyaan itu menjadi lebih populer dan lebih banyak waktu berlalu, orang-orang yang marah mulai melaporkan bahwa itu agak berhasil, tetapi hal-hal aneh bisa terjadi, atau itu sama sekali tidak berhasil, jadi pertanyaan itu secara turun-temurun dimundurkan untuk sementara waktu. Sangat menyenangkan.
Solusinya mengeksploitasi implementasi yang tepat dari deskriptor file pada sistem Anda dan, karena implementasi bervariasi secara signifikan antara nixes, keberhasilannya sepenuhnya bergantung pada sistem, pasti non-portabel, dan tidak boleh diandalkan untuk apa pun yang bahkan sangat penting.
Sekarang, dengan semua itu, jawabannya adalah:
Membuat deskriptor file lain untuk file (
exec 3<> yourfile
) kemudian menulis untuk itu (>&3
) tampaknya mengatasi baca / tulis pada dilema file yang sama. Bekerja untuk saya pada file 600K dengan awk. Namun mencoba trik yang sama menggunakan 'kucing' gagal.Melewati prependage sebagai variabel to awk (
-v TEXT="$text"
) mengatasi masalah kutipan literal yang mencegah melakukan trik ini dengan 'sed'.sumber
Ini masih menggunakan file temp, tapi setidaknya itu ada dalam satu baris:
Kredit: BASH: Sertakan Teks / Baris ke File
sumber
-
setelah itucat
?echo -n "text"
yourfile
symlink ini tidak akan melakukan apa yang Anda inginkan.ed adalah Editor Standar! http://www.gnu.org/fun/jokes/ed.msg.html
sumber
0r header.file
echo -e '0a\nyour text here\n.\nw' | ed some_file
John Mee: metode Anda tidak dijamin berfungsi, dan mungkin akan gagal jika Anda menambahkan lebih dari 4096 byte barang (setidaknya itulah yang terjadi dengan gnu awk, tapi saya rasa implementasi lain akan memiliki kendala yang sama). Tidak hanya itu akan gagal dalam kasus itu, tetapi itu akan memasuki loop tanpa akhir di mana ia akan membaca outputnya sendiri, sehingga membuat file tumbuh sampai semua ruang yang tersedia terisi.
Cobalah sendiri:
(peringatan: bunuh setelah beberapa saat atau itu akan mengisi sistem file)
Selain itu, sangat berbahaya untuk mengedit file seperti itu, dan itu saran yang sangat buruk, seolah-olah terjadi sesuatu saat file sedang diedit (crash, disk penuh) Anda hampir dijamin akan dibiarkan dengan file dalam keadaan tidak konsisten.
sumber
Tidak mungkin tanpa file temp, tapi begini oneliner
Anda dapat menggunakan alat lain seperti ed atau perl untuk melakukannya tanpa file temp.
sumber
Mungkin perlu dicatat bahwa sering kali merupakan ide yang baik untuk menghasilkan file sementara dengan aman menggunakan utilitas seperti mktemp , setidaknya jika skrip akan dijalankan dengan hak akses root. Misalnya, Anda dapat melakukan hal berikut (lagi dalam bash):
sumber
Jika Anda memerlukan ini di komputer yang Anda kontrol, instal paket "moreutils" dan gunakan "spon". Maka Anda dapat melakukan:
sumber
{ echo "prepended text"; cat myfile } | sponge myfile
Menggunakan bash heredoc Anda dapat menghindari kebutuhan file tmp:
Ini berfungsi karena $ (cat myfile) dievaluasi ketika skrip bash dievaluasi, sebelum cat dengan redirect dieksekusi.
sumber
dengan asumsi bahwa file yang ingin Anda edit adalah my.txt
Dan file yang ingin Anda tambahkan adalah tajuk
Pastikan untuk memiliki baris kosong terakhir di file header.
Sekarang Anda bisa menambahkannya dengan
Anda berakhir dengan
Sejauh yang saya tahu ini hanya bekerja di 'bash'.
sumber
this is the header
di my.txt. Bahkan setelah saya memperbarui Bash untuk4.3.42(1)-release
mendapatkan hasil yang sama.<(...)
) , jadi tidak ada jaminan yangmy.txt
dibaca secara penuh di muka , yang tanpanya teknik ini tidak akan berfungsi.Ketika Anda mulai mencoba melakukan hal-hal yang menjadi sulit dalam shell-script, saya akan sangat menyarankan melihat ke dalam penulisan ulang skrip dalam bahasa scripting yang "tepat" (Python / Perl / Ruby / etc)
Adapun untuk mendahului baris ke file, tidak mungkin untuk melakukan ini melalui perpipaan, seperti ketika Anda melakukan hal seperti
cat blah.txt | grep something > blah.txt
, itu secara tidak sengaja mengosongkan file. Ada perintah utilitas kecil yang disebutsponge
Anda dapat menginstal (Anda lakukancat blah.txt | grep something | sponge blah.txt
dan itu buffer konten file, kemudian menulisnya ke file). Ini mirip dengan file temp tetapi Anda tidak perlu melakukan itu secara eksplisit. tapi saya akan mengatakan itu persyaratan "lebih buruk" daripada, katakanlah, Perl.Mungkin ada cara untuk melakukannya melalui awk, atau serupa, tetapi jika Anda harus menggunakan shell-script, saya pikir file temp adalah cara termudah (/ hanya?) ..
sumber
Seperti yang disarankan Daniel Velkov, gunakan tee.
Bagi saya, itu solusi cerdas sederhana:
sumber
EDIT: Ini rusak. Lihat Perilaku aneh saat membuat ulang file dengan cat dan tee
Solusi untuk masalah yang ditimpa menggunakan
tee
:sumber
Yang saya gunakan. Yang ini memungkinkan Anda untuk menentukan pesanan, karakter tambahan, dll sesuai keinginan Anda:
PS: hanya itu tidak berfungsi jika file berisi teks dengan garis miring terbalik, karena itu akan ditafsirkan sebagai karakter melarikan diri
sumber
Sebagian besar untuk bersenang-senang / golf shell, tetapi
akan melakukan trik, dan tidak ada jalur pipa atau pengalihan. Tentu saja, vi / ex bukan untuk penggunaan non-aktif, jadi vi akan muncul sebentar.
sumber
Mengapa tidak menggunakan perintah ed saja (seperti yang disarankan oleh fluffle di sini)?
ed membaca seluruh file ke dalam memori dan secara otomatis melakukan edit file di tempat!
Jadi, jika file Anda tidak terlalu besar ...
Namun solusi lain akan menggunakan pegangan file terbuka seperti yang disarankan oleh Jürgen Hötzel dalam output Redirect dari sed 's / c / d /' myFile ke myFile
Semua ini bisa diletakkan pada satu baris, tentu saja.
sumber
Varian pada solusi cb0 untuk "tanpa file temp" untuk menambahkan teks tetap:
Sekali lagi ini bergantung pada eksekusi sub-shell - (()) - untuk menghindari kucing menolak memiliki file yang sama untuk input dan output.
Catatan: Menyukai solusi ini. Namun, di Mac saya file asli hilang (pikir seharusnya tidak tetapi tidak). Itu dapat diperbaiki dengan menulis solusi Anda sebagai: echo "text to prepend" | cat - file_to_be_modified | cat> tmp_file; mv tmp_file file_to_be_modified
sumber
Inilah yang saya temukan:
sumber
sumber
PERINGATAN: ini membutuhkan sedikit lebih banyak pekerjaan untuk memenuhi kebutuhan OP.
Harus ada cara untuk membuat pendekatan sed oleh @shixilun bekerja terlepas dari keraguannya. Harus ada perintah bash untuk keluar dari spasi ketika membaca file ke string pengganti sed (misalnya, ganti karakter baris baru dengan '\ n'. Perintah Shell
vis
dancat
dapat menangani karakter yang tidak dapat dicetak, tetapi bukan spasi, jadi ini tidak akan menyelesaikan OP masalah:gagal karena baris baru mentah dalam skrip pengganti, yang perlu diawali dengan karakter kelanjutan garis () dan mungkin diikuti oleh &, untuk menjaga shell dan sed bahagia, seperti jawaban SO ini
sed
memiliki batas ukuran 40K untuk perintah pencarian-ganti non-global (tanpa trailing / g setelah pola) sehingga kemungkinan akan menghindari masalah buffer overrun menakutkan dari awk yang memperingatkan anonim.sumber
sumber
Dengan $ (command) Anda dapat menulis output dari suatu perintah ke dalam variabel. Jadi saya melakukannya dalam tiga perintah dalam satu baris dan tidak ada file temp.
sumber
Jika Anda memiliki file besar (beberapa ratus kilobyte dalam kasus saya) dan akses ke python, ini jauh lebih cepat daripada
cat
solusi pipa:python -c 'f = "filename"; t = open(f).read(); open(f, "w").write("text to prepend " + t)'
sumber
Solusi dengan
printf
:Anda juga bisa:
Tetapi dalam hal ini Anda harus yakin tidak ada di
%
mana pun, termasuk konten file target, karena itu dapat ditafsirkan dan mengacaukan hasil Anda.sumber
echo
sepertinya pilihan yang lebih aman.echo "my new line\n$(cat my/file.txt)" > my/file.txt
${new_line}
, bukan file targetAnda dapat menggunakan baris perintah perl:
Di mana -i akan membuat pengganti inline file dan -0777 akan menyeruput seluruh file dan membuat ^ cocok hanya dengan permulaan. -pe akan mencetak semua baris
Atau jika my_header adalah file:
Dimana / e akan memungkinkan eval kode dalam substitusi.
sumber
di mana "my_file" adalah file untuk menambahkan "my_string" ke.
sumber
Saya menyukai pendekatan ed @ fluffle yang terbaik. Lagi pula, saklar baris perintah alat apa pun vs perintah editor yang ditulis pada dasarnya adalah hal yang sama di sini; tidak melihat solusi editor scripted "kebersihan" menjadi lebih rendah atau yang lainnya.
Inilah one-liner saya yang ditambahkan
.git/hooks/prepare-commit-msg
untuk menambahkan.gitmessage
file in-repo untuk melakukan pesan:Contoh
.gitmessage
:Saya melakukan
1r
alih - alih0r
, karena itu akan meninggalkan baris kosong siap-untuk-menulis di atas file dari template asli. Jangan meletakkan garis kosong di atas Anda.gitmessage
, Anda akan berakhir dengan dua garis kosong.-s
menekan keluaran info diagnostik ed.Sehubungan dengan melalui ini, saya menemukan bahwa untuk vim-buff juga baik untuk memiliki:
sumber
variabel, bagaimana?
sumber
Saya pikir ini adalah variasi terbersih dari ed:
sebagai fungsi:
sumber
Jika Anda menulis dalam BASH, sebenarnya, Anda bisa menerbitkan:
Itu sebenarnya dalam Contoh Kompleks yang Anda poskan sendiri dalam pertanyaan Anda sendiri.
sumber
cat - yourfile <<<"text" > /tmp/out && mv /tmp/out yourfile
, namun itu cukup berbeda dari jawaban saya bahwa itu seharusnya jawabannya sendiri.IMHO tidak ada solusi shell (dan tidak akan pernah menjadi satu) yang akan bekerja secara konsisten dan andal apa pun ukuran kedua file
myheader
danmyfile
. Alasannya adalah bahwa jika Anda ingin melakukannya tanpa berulang ke file sementara (dan tanpa membiarkan shell berulang secara diam-diam ke file sementara, misalnya melalui konstruksi sepertiexec 3<>myfile
, perpipaan ketee
, dll.Solusi "nyata" yang Anda cari perlu mengutak-atik filesystem, dan karena itu tidak tersedia di userspace dan akan bergantung pada platform: Anda meminta untuk memodifikasi pointer filesystem yang digunakan dengan
myfile
nilai saat ini dari pointer filesystem untukmyheader
dan mengganti di filesystemEOF
darimyheader
dengan link dirantai ke alamat filesystem saat ini ditunjuk olehmyfile
. Ini bukan hal sepele dan jelas tidak bisa dilakukan oleh yang bukan pengguna super, dan mungkin juga bukan oleh pengguna super ... Bermain dengan inode, dll.Anda bisa lebih atau kurang memalsukan ini menggunakan perangkat loop. Lihat misalnya utas SO ini .
sumber