Apa cara termudah untuk menambahkan string di awal setiap baris file dari baris perintah?

8

Saya mencari cara untuk menambahkan beberapa string ke awal setiap baris (string yang sama untuk setiap baris). Bukan sesuatu yang dapat dikustomisasi melainkan sesuatu yang akan mudah diingat dan tersedia pada setiap platform yang mendukung POSIX (dan setiap shell juga).

syntagma
sumber

Jawaban:

8

Anda bisa menggunakan sed:

sed -i 's/^/your_string /' your_file

Berkat komentar Stephane dan Marco, perhatikan bahwa -iopsi ini bukan POSIX. Cara POSIX untuk melakukan hal di atas adalah

sed 's/^/your_string /' your_file > tmp_copy && mv tmp_copy your_file

atau perl:

perl -pi -e 's/^/your_string /' your_file

Penjelasan

Kedua perintah melakukan substitusi regex, mengganti awal baris ( ^) dengan string yang Anda inginkan. The -iberalih di kedua perintah memastikan file tersebut diedit di tempat (yaitu perubahan tercermin dalam file bukannya dicetak ke stdout).

sedharus tersedia pada OS perlyang mendukung POSIX dan harus tersedia di sebagian besar Unices modern kecuali mungkin untuk yang telah melalui upaya menghapusnya.

Joseph R.
sumber
1
Koreksi kecil: -iSwitch tidak mengedit file pada tempatnya. Itu menciptakan file baru dan menimpa yang asli setelah selesai (bukti: perubahan inode). Tidak banyak alat yang benar-benar melakukan pengeditan di tempat, yang merupakan operasi berbahaya. Selain itu, karena Anda menyebutkan POSIX, -iswitch tidak wajib untuk POSIX yang kompatibel sed, itu adalah fitur dari beberapa implementasi tertentu.
Marco
2
sed -ibukan POSIX. Itu GNU. FreeBSD sedmemiliki opsi serupa, tetapi Anda perlu di sed -i ''sana.
Stéphane Chazelas
@ Marco Saya sadar bahwa -imembuat salinan sementara (itu sebabnya saya mengatakan perubahan tercermin dalam file asli); Maksud saya, Anda mendapatkan semantik yang sama dengan substitusi di tempat. Periksa apakah jawaban yang diperbarui sesuai dengan POSIX.
Joseph R.
Sebenarnya, perubahan tercermin dalam file baru dengan nama yang sama dengan aslinya.
Keith Thompson
1
Saya sering menggunakan $$(id proses shell saat ini) sebagai bagian dari nama file sementara; itu menghindari upaya memikirkan nama unik yang dijamin setiap saat:command filename > filename.$$ && mv filename.$$ filename
Keith Thompson
14
:|paste -d'foo ' - - - - input > output

(hanya bercanda, meskipun Anda mungkin akan menemukan itu yang tercepat dari semua solusi yang diposting di sini: -b).

Cara kanonik adalah:

sed 's/^/foo /' < input > output

Namun, itu tidak mudah diadaptasi ke string sewenang-wenang. Contohnya,

sed "s/^/$var /"

Hanya bekerja jika $vartidak mengandung, &, \, /atau karakter baris baru.

Dalam hal itu,

export var
awk '{print ENVIRON["var"], $0}'

atau

perl -pe '$_="$ENV{var} $_"'

akan bekerja lebih baik.

Stéphane Chazelas
sumber
itu sesuatu yang menarik ...: P
Rahul Patil
4

Saya menyajikan solusi menggunakan awkprepending the string "foo".

awk '{ print "foo", $0; }' input > output

awkadalah lintas-platform dan tersedia di sistem POSIX apa pun. Itu tidak melakukan pengeditan di tempat. Jika Anda ingin mengedit file tanpa membuat yang kedua, Anda harus menggunakan file sementara. Lihat sedjawaban Joseph , itu menunjukkan sintaks. Peretasan lain adalah dengan menggunakan sintaks berikut, yang pada dasarnya membuat file sementara dengan nama file yang sama dengan file asli.

{ rm file; awk '{ print "foo", $0 }' > file; } < file
Marco
sumber
reducto# wc -l foo`914 foo` Sepertinya reducto# { rm foo ; awk '{ print "prepend" , $0 }' > foo } < foo >ini tidak berhasil. Saya mencoba karena pengalihan ke asli membuat saya gugup, tetapi itu tidak akan dimulai.
kurtm
1
Contoh ini akan bekerja jika menggunakan kurung di luar daripada kurung kurawal.
kurtm
4

Anda dapat menghindari masalah pengeditan di tempat dengan alat streaming dengan menggunakan alat yang biasanya melakukan pengeditan di tempat - editor!

ex sample.txt -c "%s/^/foo /" -c wq

Ada keuntungan tambahan bahwa perintahnya mudah dan jelas bagi siapa saja yang berpengalaman dalam satu editor yang benar.

Mike DeAngelo
sumber
2

Anda dapat menggunakannya perluntuk melakukan ini:

$ perl -pi -e 's/^/mystring /' afile.txt

Contoh

Buat file sampel.

$ seq 5 > afile.txt

$ cat afile.txt
1
2
3
4
5

Jalankan perintah di atas:

$ perl -pi -e 's/^/mystring /' afile.txt

$ cat afile.txt
mystring 1
mystring 2
mystring 3
mystring 4
mystring 5
slm
sumber
Perl tampaknya bersifat universal saat ini, tetapi untuk waktu yang lama tidak. Dan saya bertaruh ada beberapa varian UNIX langka di luar sana yang dengan tegas menolak untuk memiliki perl sebagai bagian dari basis. Sesuatu yang harus diperhatikan.
kurtm
@kurtm lihat diskusi di sini . Rupanya, AIX tidak memiliki Perl secara default dan juga sistem embedded.
terdon
2
@ DavidSainty - cukup universal. Q ditandai dengan Bash jadi saya merasa sangat sulit untuk membayangkan sistem yang memiliki Bash tetapi tidak Perl. Bagaimanapun, inilah salah satu dari 5 jawaban, beberapa yang lain menunjukkan cara menggunakan sed, saya menunjukkan cara menggunakan Perl .... tidak mencari perang suci dalam masalah ini.
slm
1
@DavidSainty Ternyata hanya OpenBSD. Saya kira saya membuat asumsi karena orang-orang Terbuka cenderung konservatif tentang apa yang mereka izinkan di pangkalan. OpenBSD secara definitif memang memilikinya.
kurtm
1
@slm: " Saya merasa sangat sulit untuk membayangkan sistem yang memiliki Bash tetapi tidak Perl ". Saya memiliki beberapa sistem seperti duduk di meja saya. (Mereka kebetulan merupakan sistem yang tertanam.)
Keith Thompson
1

Cukup menggunakan Bash

 while IFS= read -r line; do echo "foo" "${line}" ; done  < input > Output

Menggunakan Python

python -c "import sys; print 'foo '.join([ l for l in sys.stdin.readlines() ])" < input > Output

Jika Anda ingin mengedit di tempat

import fileinput
import sys

for line in fileinput.input(['inputfile'], inplace=True):
    sys.stdout.write('foo {l}'.format(l=line))

Tautan referensi

Rahul Patil
sumber
Mengapa ini bekerja lebih cepat daripada awk?
Rahul Patil
1
Ini hanya akan bekerja lebih cepat daripada awkpada file yang sangat kecil. Perilaku bervariasi di seluruh implementasi gema dan strips memimpin dan tertinggal kosong dan proses backslash khusus.
Stéphane Chazelas
@StephaneChazelas Ya. Anda 100% benar, baru saja diuji ... paste.ubuntu.com/6210934
Rahul Patil
prefix () { while IFS= read -r REPLY; do printf "%s%s\n" "$1" "$REPLY"; done; }seharusnya lebih benar.
Mat
1
Mengapa {}? Saya pikir @Matt menyarankan Anda membuatnya menjadi fungsi bernama, apa gunanya {}tanpa nama fungsi?
terdon
-1

Atau Anda dapat melakukan hal berikut:

vi filename.txt

Esc(untuk memastikan Anda dalam NORMALmode), lalu masukkan perintah berikut:

:1,$ s/^/mystring
Dino
sumber
Perhatikan bahwa karena pengguna bertanya tentang setiap baris file, Anda dapat menggantinya 1,$ dengan sederhana %. Ini yang membuat perintah :%s/^/string/.
HalosGhost