Apakah ada perintah Unix untuk menambahkan beberapa data string ke file teks?
Sesuatu seperti:
prepend "to be prepended" text.txt
<<(echo "to be prepended") < text.txt | sponge text.txt
Apakah ada perintah Unix untuk menambahkan beberapa data string ke file teks?
Sesuatu seperti:
prepend "to be prepended" text.txt
<<(echo "to be prepended") < text.txt | sponge text.txt
Jawaban:
sed -i.old '1s;^;to be prepended;' inFile
-i
menulis perubahan di tempat dan membuat cadangan jika ada ekstensi yang diberikan. (Dalam hal ini, .old
)1s;^;to be prepended;
mengganti awal baris pertama dengan string pengganti yang diberikan, menggunakan ;
sebagai pembatas perintah.\n
setelah prepend; tergantung kebutuhan mereka. Solusi yang rapi.
inFile
direktori include di jalurnya?
\n
. Seharusnya sudah baca komentarnya dulu. Sial.
'1s;^;my-prepended-line\;\n;'
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
git config --get-regex $arg | sed -r 's/\t{3}/\\n/g';
dan ini kacau karena mengubah \t
dan \n
.
echo "to be prepended"$'\n'"$(cat text.txt)"
Saya terkejut tidak ada yang menyebutkan ini.
cat <(echo "before") text.txt > newfile.txt
yang bisa dibilang lebih alami daripada jawaban yang diterima (mencetak sesuatu dan menyalurkannya ke dalam perintah substitusi secara leksikografis berlawanan dengan intuisi).
... dan membajak apa yang dikatakan ryan di atas, dengan sponge
Anda tidak memerlukan file sementara:
sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt
EDIT: Sepertinya ini tidak berfungsi di Bourne Shell /bin/sh
Menggunakan here-string - <<<
, Anda dapat melakukan:
<<< "to be prepended" < text.txt | sponge text.txt
<<(echo "to be prepended") < text.txt
dan <<< "to be prepended" < text.txt
konstruksi tidak berfungsi dalam bash; mereka membutuhkan zsh.
Ini adalah satu kemungkinan:
(echo "to be prepended"; cat text.txt) > newfile.txt
Anda mungkin tidak akan dengan mudah menggunakan file perantara.
Alternatif (bisa merepotkan dengan keluarnya shell):
sed -i '0,/^/s//to be prepended/' text.txt
cat <(echo "to be prepended") text.txt > newfile.txt
. Kalau dipikir-pikir, saya tidak yakin milik saya terkait, jadi saya memposting jawaban terpisah.
Ini akan bekerja untuk membentuk keluaran. Itu - berarti input standar, yang disediakan melalui pipa dari echo.
echo -e "to be prepended \n another line" | cat - text.txt
Untuk menulis ulang file, file sementara diperlukan karena tidak dapat menyalurkan kembali ke file input.
echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
text.txt
seperti yang diminta, tetapi menampilkannya di stdout. Output dapat disalurkan ke file yang berbeda jika itu berfungsi untuk OP
Lebih suka jawaban Adam
Kita bisa mempermudah penggunaan spons . Sekarang kita tidak perlu membuat file sementara dan mengganti namanya dengan
echo -e "to be prepended \n another line" | cat - text.txt | sponge text.txt
catatan:
Melakukannya mungkin memiliki efek samping yang tidak terduga, terutama berpotensi mengganti symlink dengan file biasa, berakhir dengan izin yang berbeda pada file tersebut, dan mengubah tanggal pembuatan (lahir) file.
sed -i
, seperti dalam jawaban Pangeran John Wesley , mencoba untuk setidaknya memulihkan izin asli, tetapi batasan lain juga berlaku.
Berikut adalah alternatif sederhana yang menggunakan file sementara (ini menghindari membaca seluruh file input ke dalam memori seperti yang dilakukan solusi shime ):
{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt
Menggunakan perintah grup ( { ...; ...; }
) sedikit lebih efisien daripada menggunakan subkulit ( (...; ...)
), seperti dalam solusi 0xC0000022L .
Keunggulannya adalah:
Sangat mudah untuk mengontrol apakah teks baru harus langsung ditambahkan ke baris pertama atau apakah harus disisipkan sebagai baris baru (cukup tambahkan \n
ke printf
argumen).
tidak seperti sed
solusinya, ini berfungsi jika file input kosong ( 0
byte).
Itu sed
solusi dapat disederhanakan jika tujuannya adalah untuk tambahkan satu atau lebih seluruh baris dengan isi yang ada (dengan asumsi file input tidak kosong):
sed
's i
menyisipkan fungsi seluruh baris:
Dengan GNU sed
:
# Prepends 'to be prepended' *followed by a newline*, i.e. inserts a new line.
# To prepend multiple lines, use '\n' as part of the text.
# -i.old creates a backup of the input file with extension '.old'
sed -i.old '1 i\to be prepended' inFile
Varian portabel yang juga berfungsi dengan macOS / BSD sed
:
# Prepends 'to be prepended' *followed by a newline*
# To prepend multiple lines, escape the ends of intermediate
# lines with '\'
sed -i.old -e '1 i\
to be prepended' inFile
Perhatikan bahwa baris baru literal setelah \
diperlukan.
Menggunakan Yang Mulia ed
utilitas POSIX yang :
catatan:
ed
selalu membaca file input secara keseluruhan ke dalam memori terlebih dahulu.Untuk menambahkan langsung ke baris pertama (seperti sed
, ini tidak akan berfungsi jika file input benar-benar kosong ( 0
byte)):
ed -s text.txt <<EOF
1 s/^/to be prepended/
w
EOF
-s
tertindas ed
pesan status yang .ed
sebagai multi-baris here-document ( <<EOF\n...\nEOF
), yaitu melalui stdin ; secara default ekspansi tali yang dilakukan di dokumen tersebut (variabel shell yang diinterpolasi); mengutip pembatas pembukaan untuk menekannya (misalnya,<<'EOF'
).1
menjadikan baris pertama sebagai baris saat inis
melakukan substitusi string berbasis regex pada baris saat ini, seperti sed
; Anda dapat menyertakan baris baru literal dalam teks substitusi, tetapi baris tersebut harus di- \
escape.w
menulis hasilnya kembali ke file input (untuk pengujian, ganti w
dengan ,p
untuk hanya mencetak hasil, tanpa mengubah file input).Untuk menambahkan satu atau lebih baris penuh :
Seperti halnya sed
, i
fungsi tersebut selalu menambahkan baris baru ke teks yang akan disisipkan.
ed -s text.txt <<EOF
0 i
line 1
line 2
.
w
EOF
0 i
membuat 0
(awal file) baris saat ini dan memulai mode insert ( i
); perhatikan bahwa nomor baris 1
didasarkan sebaliknya ..
barisnya sendiri.Mungkin tidak ada bawaan, tetapi Anda dapat menulis sendiri dengan mudah, seperti ini:
#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"
Sesuatu seperti itu setidaknya ...
$$
tidak cukup untuk kode produksi (serangan symlink google); tapi itu pasti lebih baik daripada nama file statis.
mktemp
Dalam beberapa keadaan, teks yang ditambahkan mungkin hanya tersedia dari stdin. Maka kombinasi ini akan bekerja.
echo "to be prepended" | cat - text.txt | tee text.txt
Jika Anda ingin menghilangkan tee
keluaran, tambahkan > /dev/null
.
tee
tidak akan memanjat text.txt
sebelum cat
membacanya? Saya kira tidak - yang akan membuat solusi ini berbahaya bagi kesehatan file.
lenA=1000000; yes a | head -c $lenA > a.txt; lenB=10000; b=$(yes b | head -c $lenB); echo "$b" | cat - a.txt | tee a.txt > /dev/null
. Jika lenA
1000000 (file 1Mb) dan lenB
10000 (10Kb teks tambahan), maka file "a.txt" ditimpa dengan 20Kb huruf "b". Ini benar-benar rusak. Sekarang, jika Anda menggunakan 1Mb a.txt dan 1Mb teks untuk menambahkan, tee
masuk ke loop menghasilkan file 7Gb +, saya harus menghentikan perintah. Jadi, jelas hasilnya tidak bisa ditebak untuk ukuran besar. Saya tidak memiliki informasi apakah itu harus berfungsi pada ukuran kecil.
Larutan:
printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt
Perhatikan bahwa ini aman untuk semua jenis masukan, karena tidak ada perluasan. Misalnya, jika Anda ingin menambahkan !@#$%^&*()ugly text\n\t\n
, itu hanya akan berfungsi:
printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt
Bagian terakhir yang tersisa untuk dipertimbangkan adalah penghapusan spasi di akhir file selama penggantian perintah "$(cat file.txt)"
. Semua solusi untuk ini relatif kompleks. Jika Anda ingin mempertahankan baris baru di akhir file.txt, lihat ini: https://stackoverflow.com/a/22607352/1091436
file.txt
lebih besar dari yang dapat dimasukkan ke dalam daftar argumen printf
.
Cara lain menggunakan sed
:
sed -i.old '1 {i to be prepended
}' inFile
Jika garis yang akan ditambahkan multiline:
sed -i.old '1 {i\
to be prepended\
multiline
}' inFile
sed -i '1ito be prepended' inFile
- atau hanya diperbolehkan untuk GNU sed?
sed
, i
perintah ini diikuti dengan garis miring terbalik dan baris baru, dan setiap baris masukan kecuali yang terakhir berakhir dengan garis miring terbalik juga. GNU sed
mengizinkan singkatan di sepanjang baris yang Anda tanyakan, tetapi hanya GNU sed
yang melakukannya. '
Seperti yang diuji di Bash (di Ubuntu), jika dimulai dengan file uji melalui;
echo "Original Line" > test_file.txt
Anda bisa mengeksekusi;
echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt
atau, jika versi bash terlalu tua untuk $ (), Anda dapat menggunakan backticks;
echo "`echo "New Line"; cat test_file.txt`" > test_file.txt
dan menerima konten berikut dari "test_file.txt";
New Line
Original Line
Tidak ada file perantara, hanya bash / echo.
Solusi lain yang cukup mudah adalah:
$ echo -e "string\n" $(cat file)
cat
perluasan parameter dalam tanda kutip ganda adalah alasan yang cukup bagus untuk downvote . Kode ini membagi konten file menjadi kata-kata, dan meneruskan setiap kata tersebut sebagai argumen terpisah ke echo
. Anda kehilangan batas argumen asli, Anda kehilangan baris baru / tab / dll., Dan string seperti \t
dan \n
dalam teks asli diganti dengan tab dan baris baru alih-alih disimpan sebagaimana mestinya.
Jika Anda menyukai vi / vim, ini mungkin lebih sesuai gaya Anda.
printf '0i\n%s\n.\nwq\n' prepend-text | ed file
Saya akan merekomendasikan untuk mendefinisikan sebuah fungsi dan kemudian mengimpor dan menggunakannya jika diperlukan.
prepend_to_file() {
file=$1
text=$2
if ! [[ -f $file ]] then
touch $file
fi
echo "$text" | cat - $file > $file.new
mv -f $file.new $file
}
Kemudian gunakan seperti ini:
prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"
Konten file Anda kemudian akan menjadi:
This is second
This is first
Saya akan menggunakan pendekatan ini untuk mengimplementasikan pembaru log perubahan.