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" .
\n
dalam 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
sh
Solusi yang kompatibel dengan POSIX adalah:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
argumen. 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 sed
jika 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/name
di awal. Kami tidak butuh sed
!
Mengingat bahwa bash memberi kita variabel ajaib $PWD
dan $HOME
, kita dapat:
echo "${PWD/#$HOME/\~}"
EDIT: Terima kasih untuk Mark Haferkamp dalam komentar untuk catatan tentang mengutip / melarikan diri ~
. *
Perhatikan bagaimana variabel $HOME
berisi garis miring tetapi ini tidak merusak apa pun.
Bacaan lebih lanjut: Panduan Bash-Scripting Lanjutan .
Jika menggunakan sed
adalah suatu keharusan, pastikan untuk melepaskan setiap karakter .
sed
dengan pwd
perintah untuk menghindari mendefinisikan variabel baru setiap kali kebiasaan saya $PS1
berjalan. 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 $PS1
puasa Anda: Anda mungkin juga tertarik $PROMPT_COMMAND
jika Anda lebih nyaman menggunakan bahasa pemrograman lain dan ingin membuat kode prompt yang dikompilasi.
echo "${PWD/#$HOME/~}"
tidak menggantikan $HOME
dengan 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 uname
tanpa 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 sed
jawaban 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 $t
dalam $f
dengan [ "${f%$t*}" != "$f" ]
yang akan mengevaluasi benar jika $f
string 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"