Jawaban:
sed -i 's/original/new/g' file.txt
Penjelasan:
sed
= Streaming Editor-i
= di tempat (mis. menyimpan kembali ke file asli)String perintah:
s
= perintah penggantioriginal
= ekspresi reguler yang menggambarkan kata yang akan diganti (atau hanya kata itu sendiri)new
= teks untuk menggantikannyag
= global (mis. ganti semua dan bukan hanya kejadian pertama)file.txt
= nama file
sed
akan cocok dengan mereka. Tambahkan -r
bendera jika Anda ingin menggunakan RE yang diperluas sebagai gantinya.
/
karakter yang harus Anda cocokkan, Anda bisa menggunakan beberapa karakter lain sebagai pemisah (mis 's_old/text_new/text_g'
.). Jika tidak, Anda dapat meletakkan \
sebelum apa pun $ * . [ \ ^
untuk mendapatkan karakter literal.
sed -i '.bak' 's/original/new/g' file.txt
juga dapat dijalankan dengan ekstensi panjang nol sed -i '' 's/original/new/g' file.txt
, yang tidak akan menghasilkan cadangan.
Ada sejumlah cara berbeda untuk melakukan ini. Salah satunya menggunakan sed
dan Regex. SED adalah Editor Stream untuk memfilter dan mengubah teks. Salah satu contohnya adalah sebagai berikut:
marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog
Cara lain yang mungkin lebih masuk akal daripada < strin
dan > strout
adalah dengan pipa!
marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai
The quick brown fox jumped over the lazy sleeping dog
cat
di cat file | sed '...'
tidak perlu. Anda bisa langsung bilang sed '...' file
.
sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly
akan mengambil file yarly dan melakukan 2 perubahan di tempat sambil membuat cadangan. Menggunakan time bash -c "$COMMAND"
waktu itu menunjukkan bahwa versi ini ~ 5 kali lebih cepat.
Ada banyak cara untuk mencapainya. Bergantung pada kerumitan apa yang ingin dicapai dengan penggantian string, dan tergantung pada alat yang akrab dengan pengguna, beberapa metode mungkin lebih disukai daripada yang lain.
Dalam jawaban ini saya menggunakan input.txt
file sederhana , yang dapat Anda gunakan untuk menguji semua contoh yang disediakan di sini. Isi file:
roses are red , violets are blue
This is an input.txt and this doesn't rhyme
Bash sebenarnya tidak dimaksudkan untuk pemrosesan teks, tetapi penggantian sederhana dapat dilakukan melalui ekspansi parameter , khususnya di sini kita dapat menggunakan struktur sederhana ${parameter/old_string/new_string}
.
#!/bin/bash
while IFS= read -r line
do
case "$line" in
*blue*) printf "%s\n" "${line/blue/azure}" ;;
*) printf "%s\n" "$line" ;;
esac
done < input.txt
Skrip kecil ini tidak melakukan penggantian di tempat, artinya Anda harus menyimpan teks baru ke file baru, dan menyingkirkan file lama, atau mv new.txt old.txt
Catatan: jika Anda ingin tahu mengapa while IFS= read -r ; do ... done < input.txt
digunakan, ini pada dasarnya cara shell membaca baris per baris. Lihat ini untuk referensi.
AWK, sebagai utilitas pemrosesan teks, cukup sesuai untuk tugas tersebut. Ia dapat melakukan penggantian sederhana dan yang lebih maju berdasarkan pada ekspresi reguler . Ini menyediakan dua fungsi: sub()
dan gsub()
. Yang pertama hanya menggantikan kejadian pertama, sedangkan yang kedua - menggantikan kejadian di seluruh string. Misalnya, jika kita memiliki string one potato two potato
, ini akan menjadi hasilnya:
$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'
one banana two banana
$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'
one banana two potato
AWK dapat mengambil file input sebagai argumen, jadi melakukan hal yang sama dengannya input.txt
, akan mudah:
awk '{sub(/blue/,"azure")}1' input.txt
Bergantung pada versi AWK yang Anda miliki, mungkin saja ada atau tidak ada pengeditan di tempat, maka praktik yang biasa dilakukan adalah menyimpan dan mengganti teks baru. Misalnya sesuatu seperti ini:
awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt
Sed adalah editor baris. Itu juga menggunakan ekspresi reguler, tetapi untuk penggantian sederhana itu cukup untuk melakukan:
sed 's/blue/azure/' input.txt
Apa yang baik tentang alat ini adalah memiliki pengeditan di tempat, yang dapat Anda aktifkan dengan -i
flag.
Perl adalah alat lain yang sering digunakan untuk pemrosesan teks, tetapi merupakan bahasa tujuan umum, dan digunakan dalam jaringan, administrasi sistem, aplikasi desktop, dan banyak tempat lainnya. Ini meminjam banyak konsep / fitur dari bahasa lain seperti C, sed, awk, dan lainnya. Substitusi sederhana dapat dilakukan sebagai berikut:
perl -pe 's/blue/azure/' input.txt
Seperti sed, perl juga memiliki flag -i.
Bahasa ini sangat fleksibel dan juga digunakan dalam berbagai aplikasi. Ini memiliki banyak fungsi untuk bekerja dengan string, di antaranya adalah replace()
, jadi jika Anda memiliki variabel like var="Hello World"
, Anda bisa melakukannyavar.replace("Hello","Good Morning")
Cara sederhana untuk membaca file dan mengganti string di dalamnya adalah sebagai berikut:
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt
Namun, dengan Python, Anda juga perlu meng-output ke file baru, yang juga dapat Anda lakukan dari dalam skrip itu sendiri. Misalnya, ini yang sederhana:
#!/usr/bin/env python
import sys
import os
import tempfile
tmp=tempfile.mkstemp()
with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:
for line in fd1:
line = line.replace('blue','azure')
fd2.write(line)
os.rename(tmp[1],sys.argv[1])
Script ini disebut dengan input.txt
argumen baris perintah. Perintah yang tepat untuk menjalankan skrip python dengan argumen command-line adalah
$ ./myscript.py input.txt
atau
$ python ./myscript.py input.txt
Tentu saja, pastikan itu ./myscript.py
ada di direktori kerja Anda saat ini dan untuk cara pertama, pastikan direktori tersebut dapat dieksekusichmod +x ./myscript.py
Python juga dapat memiliki ekspresi reguler, khususnya, ada re
modul, yang memiliki re.sub()
fungsi, yang dapat digunakan untuk penggantian yang lebih maju.
tr
perintah di unix
tr
adalah alat hebat lainnya, tetapi perhatikan bahwa itu untuk mengganti sekumpulan karakter (misalnya tr abc cde
akan diterjemahkan a
menjadi c
, b
untuk d
. Ini sedikit berbeda dari mengganti seluruh kata dengan sed
ataupython
Anda dapat menggunakan Vim dalam mode Ex:
ex -s -c '%s/OLD/NEW/g|x' file
%
pilih semua garis
s
pengganti
g
ganti semua instance di setiap baris
x
tulis jika telah dilakukan perubahan (sudah) dan keluar
Melalui perintah gsub awk,
awk '{gsub(/pattern/,"replacement")}' file
Contoh:
awk '{gsub(/1/,"0");}' file
Dalam contoh di atas, semua 1 digantikan oleh 0 terlepas dari kolom di mana ia berada.
Jika Anda ingin melakukan penggantian pada kolom tertentu, maka lakukan seperti ini,
awk '{gsub(/pattern/,"replacement",column_number)}' file
Contoh:
awk '{gsub(/1/,"0",$1);}' file
Ia menggantikan 1 dengan 0 pada kolom pertama saja.
Melalui Perl,
$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
inotifywait
bawah sh
env, dan melaporkan data dalam format CSV (karena format khusus bersifat buggy). Saya kemudian menemukan tidak ada cara sederhana untuk menangani dokumen CSV dalam skrip shell ... Dan saya ingin itu sangat ringan. Jadi saya memulai skrip yang cukup sederhana untuk mem-parsing dan melaporkan CSV. Saya membaca spesifikasi CSV dan memperhatikannya lebih rumit dari yang saya harapkan dan mendukung nilai multiline yang dibungkus dengan tanda kutip ganda. Saya mengandalkan sed
tokenization tetapi segera menyadari bahwa apa pun yang sed
disebut multilines hingga dua baris. Lalu bagaimana jika salah satu nilai CSV saya menjangkau lebih dari dua baris?
sed
adalah s tream ed itor , karena Anda dapat menggunakan |
(pipa) untuk mengirim standar stream (STDIN dan STDOUT khusus) melalui sed
dan mengubah mereka pemrograman dengan cepat, membuatnya menjadi alat yang berguna dalam tradisi filsafat Unix; tetapi dapat mengedit file secara langsung juga, menggunakan -i
parameter yang disebutkan di bawah ini.
Pertimbangkan yang berikut ini :
sed -i -e 's/few/asd/g' hello.txt
s/
digunakan untuk s ubstitute ekspresi ditemukan few
dengan asd
:
Beberapa, berani.
ASD, pemberani.
/g
singkatan "global", artinya melakukan ini untuk seluruh lini. Jika Anda meninggalkan /g
(dengan s/few/asd/
, selalu harus ada tiga garis miring tidak peduli apa) dan few
muncul dua kali pada baris yang sama, hanya yang pertama few
diubah menjadi asd
:
Beberapa pria, beberapa wanita, pemberani.
Laki-laki asd, beberapa perempuan, pemberani.
Ini berguna dalam beberapa keadaan, seperti mengubah karakter khusus di awal baris (misalnya, mengganti simbol lebih besar dari yang digunakan beberapa orang untuk mengutip materi sebelumnya di utas email dengan tab horizontal sambil meninggalkan ketidaksamaan aljabar yang dikutip kemudian di baris tersebut). tidak tersentuh), tetapi dalam contoh Anda di mana Anda menentukan bahwa di mana saja few
terjadi itu harus diganti, pastikan Anda memilikinya /g
.
Dua opsi berikut (bendera) digabungkan menjadi satu -ie
,:
-i
Pilihan ini digunakan untuk mengedit i n tempat pada file tersebut hello.txt
.
-e
Opsi menunjukkan e xpression / perintah untuk dijalankan, dalam hal ini s/
.
Catatan: Penting bagi Anda -i -e
untuk mencari / mengganti. Jika ya -ie
, Anda membuat cadangan setiap file dengan huruf 'e' ditambahkan.
Anda bisa melakukan ini:
locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g"
Contoh: untuk mengganti semua kejadian [logdir ',' '] (tanpa []) dengan [logdir', os.getcwd ()] di semua file yang merupakan hasil dari perintah loc, lakukan:
ex1:
locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"
ex2:
locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"
di mana [tensorboard / program.py] adalah file untuk dicari
logdir', ''
-> /logdir', os.getcwd()
) membuat jawaban ini sulit untuk diurai. Juga, ada baiknya menentukan bahwa jawaban Anda pertama-tama menemukan file yang akan digunakan, karena itu bukan bagian dari pertanyaan.