Saya memiliki "Saya suka Suzi dan Menikah" dan saya ingin mengubah "Suzi" menjadi "Sara".
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Hasilnya harus seperti ini:
firstString="I love Sara and Marry"
Saya memiliki "Saya suka Suzi dan Menikah" dan saya ingin mengubah "Suzi" menjadi "Sara".
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
Hasilnya harus seperti ini:
firstString="I love Sara and Marry"
Jawaban:
Untuk mengganti kemunculan pertama pola dengan string yang diberikan, gunakan :${parameter/pattern/string}
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"
# prints 'I love Sara and Marry'
Untuk mengganti semua kejadian, gunakan :${parameter//pattern/string}
message='The secret code is 12345'
echo "${message//[0-9]/X}"
# prints 'The secret code is XXXXX'
(Ini didokumentasikan dalam dalam Pedoman Bash Reference , §3.5.3 "Shell Parameter Ekspansi" .)
Perhatikan bahwa fitur ini tidak ditentukan oleh POSIX - ini adalah ekstensi Bash - jadi tidak semua shell Unix menerapkannya. Untuk dokumentasi POSIX yang relevan, lihat Spesifikasi Pangkalan Standar Teknis Grup Terbuka, Edisi 7 , volume Shell & Utilities , §2.6.2 "Ekspansi Parameter" .
\ndalam konteks itu akan mewakili dirinya sendiri, bukan baris baru. Saya tidak punya Bash berguna sekarang untuk menguji, tetapi Anda harus dapat menulis sesuatu seperti $STRING="${STRING/$'\n'/<br />}",. (Meskipun Anda mungkin ingin STRING//- ganti semua - bukan hanya STRING/.)
echo ${my string foo/foo/bar}. Anda perluinput="my string foo"; echo ${input/foo/bar}
//secara langsung, ia menyebutkan apa yang terjadi "Jika pola dimulai dengan ' /'" (yang bahkan tidak akurat, karena sisa kalimat itu mengasumsikan bahwa tambahan /itu sebenarnya bukan bagian dari polanya) - tapi saya tidak tahu sumber yang lebih baik.
Ini dapat dilakukan sepenuhnya dengan manipulasi string bash:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
Itu hanya akan menggantikan kejadian pertama; untuk mengganti semuanya, gandakan tebasan pertama:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"
Untuk Dash semua posting sebelumnya tidak berfungsi
shSolusi yang kompatibel dengan POSIX adalah:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echoargumen. Itu menipu bekerja tanpa mengutip dengan string sederhana, tetapi dengan mudah istirahat pada string input nontrivial (spasi tidak teratur, karakter meta shell, dll).
coba ini:
sed "s/Suzi/$secondString/g" <<<"$firstString"
Lebih baik menggunakan bash daripada sedjika string memiliki karakter RegExp.
echo ${first_string/Suzi/$second_string}
Ini portabel untuk Windows dan bekerja dengan setidaknya setua Bash 3.1.
Untuk menunjukkan bahwa Anda tidak perlu terlalu khawatir tentang melarikan diri, mari kita ubah ini:
/home/name/foo/bar
Ke dalam ini:
~/foo/bar
Tetapi hanya jika /home/namedi awal. Kami tidak butuh sed!
Mengingat bahwa bash memberi kita variabel ajaib $PWDdan $HOME, kita dapat:
echo "${PWD/#$HOME/\~}"
EDIT: Terima kasih untuk Mark Haferkamp dalam komentar untuk catatan tentang mengutip / melarikan diri ~. *
Perhatikan bagaimana variabel $HOMEberisi garis miring tetapi ini tidak merusak apa pun.
Bacaan lebih lanjut: Panduan Bash-Scripting Lanjutan .
Jika menggunakan sedadalah suatu keharusan, pastikan untuk melepaskan setiap karakter .
seddengan pwdperintah untuk menghindari mendefinisikan variabel baru setiap kali kebiasaan saya $PS1berjalan. Apakah Bash menyediakan cara yang lebih umum daripada variabel sihir untuk menggunakan output dari perintah untuk penggantian string? Adapun kode Anda, saya harus melarikan diri ~untuk menjaga Bash dari mengembangkannya menjadi $ HOME. Juga, apa yang dilakukan #perintah Anda?
~": perhatikan bagaimana saya mengutip barang. Ingatlah untuk selalu mengutip barang! Dan ini tidak hanya berfungsi untuk variabel ajaib: variabel apa pun dapat diganti, mendapatkan panjang string, dan banyak lagi, dalam bash. Selamat mencoba $PS1puasa Anda: Anda mungkin juga tertarik $PROMPT_COMMANDjika Anda lebih nyaman menggunakan bahasa pemrograman lain dan ingin membuat kode prompt yang dikompilasi.
echo "${PWD/#$HOME/~}"tidak menggantikan $HOMEdengan saya ~. Mengganti ~dengan \~atau '~'berfungsi. Semua ini bekerja pada Bash 4.2.53 pada distro lain. Bisakah Anda memperbarui posting Anda untuk mengutip atau menghindari ~kompatibilitas yang lebih baik? Apa yang saya maksud dengan pertanyaan "variabel ajaib" saya adalah: Dapatkah saya menggunakan substitusi variabel Bash pada, misalnya, keluaran unametanpa menyimpannya sebagai variabel terlebih dahulu? Sedangkan untuk pribadi saya $PROMPT_COMMAND, ini rumit .
Jika besok Anda memutuskan tidak mencintai Marry, ia juga bisa diganti:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txt
Pasti ada 50 cara untuk meninggalkan kekasih Anda.
Karena saya tidak bisa menambahkan komentar. @ruaka Agar contohnya lebih mudah dibaca, tulis seperti ini
full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
Pure POSIX metode shell, yang tidak seperti Roman Kazanovskyi 's sedjawaban berbasis tidak memerlukan alat eksternal, hanya shell sendiri asli ekspansi parameter . Perhatikan bahwa nama file yang panjang diminimalkan sehingga kode lebih cocok pada satu baris:
f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"
Keluaran:
I love Sara and Marry
Bagaimana itu bekerja:
Hapus Pola Sufiks Terkecil. "${f%$t*}"mengembalikan " I love" jika sufiks $t" Suzi*" ada di $f" ". I love Suzi and Marry
Tetapi jika t=Zelda, maka "${f%$t*}"tidak menghapus apa pun, dan mengembalikan seluruh string " I love Suzi and Marry".
Ini digunakan untuk menguji apakah $tdalam $fdengan [ "${f%$t*}" != "$f" ]yang akan mengevaluasi benar jika $fstring berisi " Suzi*" dan palsu jika tidak.
Jika pengujian mengembalikan true , buat string yang diinginkan menggunakan Hapus Pola Sufiks Terkecil ${f%$t*} " I love" dan Hapus Pola Awalan Terkecil ${f#*$t} " and Marry", dengan string ke - 2$s " Sara" di antaranya.
Saya tahu ini sudah tua tetapi karena tidak ada yang menyebutkan tentang menggunakan awk:
firstString="I love Suzi and Marry"
echo $firstString | awk '{gsub("Suzi","Sara"); print}'
echo [string] | sed "s/[original]/[target]/g"