@ruakh bagaimana cara menulis pernyataan ini dengan atau kondisi. Hanya jika saya ingin mengganti Suzi atau Menikah dengan string baru.
Priyatham51
3
@ Priyatham51: Tidak ada fitur bawaan untuk itu. Cukup ganti satu, lalu yang lain.
ruakh
4
@ Bun: Tidak, karena \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/.)
ruakh
25
Agar jelas, karena ini sedikit membingungkan saya, bagian pertama harus menjadi referensi variabel. Anda tidak bisa melakukannya echo ${my string foo/foo/bar}. Anda perluinput="my string foo"; echo ${input/foo/bar}
Henrik N
2
@mgutt: Jawaban ini terhubung ke dokumentasi yang relevan. Dokumentasi tidak sempurna - misalnya, alih-alih menyebutkan //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.
ruakh
208
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"
Apa gunanya memiliki jawaban yang menduplikasi jawaban yang diterima, alih-alih mengedit jawaban yang diterima dengan opsi penggantian global? Dan menambahkan bahwa regexps didukung, sambil melakukannya. Dan menjelaskan apa yang terjadi dengan "substitusi buruk". Anda memiliki cukup poin,
@Kevin
6
Tampaknya mereka berdua menjawab di menit yang sama: O
Jamie Hutber
76
Untuk Dash semua posting sebelumnya tidak berfungsi
shSolusi yang kompatibel dengan POSIX adalah:
result=$(echo "$firstString"| sed "s/Suzi/$secondString/")
Saya mendapatkan ini: $ echo $ (echo $ firstString | sed 's / Suzi / $ secondString / g') Saya suka $ secondString dan Menikah
Qstnr_La
2
@Qstnr_La menggunakan tanda kutip ganda untuk substitusi variabel:result=$(echo $firstString | sed "s/Suzi/$secondString/g")
emc
1
Plus 1 untuk menunjukkan cara output ke variabel juga. Terima kasih!
Chef Firaun
2
Saya memperbaiki tanda kutip tunggal dan juga menambahkan tanda kutip yang hilang di sekitar echoargumen. Itu menipu bekerja tanpa mengutip dengan string sederhana, tetapi dengan mudah istirahat pada string input nontrivial (spasi tidak teratur, karakter meta shell, dll).
tripleee
Dalam sh (AWS Codebuild / Ubuntu sh) saya menemukan bahwa saya perlu satu tebasan pada akhirnya, bukan ganda. Saya akan mengedit komentar karena komentar di atas juga menunjukkan garis miring.
Anda sebenarnya tidak membutuhkan Sed untuk ini; Bash mendukung penggantian semacam ini secara asli.
ruakh
12
Saya kira ini ditandai "bash" tetapi datang ke sini karena membutuhkan sesuatu yang sederhana untuk shell lain. Ini adalah alternatif ringkas yang bagus untuk apa yang wiki.ubuntu.com/... buat seperti yang saya butuhkan.
natevw
3
Ini berfungsi baik untuk ash / dash atau POSIX sh lainnya.
Yoshua Wuyts
2
Saya mendapatkan galat : -e ekspresi # 1, char 9: opsi tidak diketahui untuk `s
Nam G VU
1
Jawaban pertama yang bekerja dengan stdin, bagus untuk string pipelining.
Dinei
46
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.
Jawaban ini menghentikan saya dari menggunakan 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?
Mark Haferkamp
1
@MarkHaferkamp Lihat ini dari tautan "bacaan lanjutan yang disarankan". Tentang "lolos dari ~": 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.
Camilo Martin
Tautan "bacaan lebih lanjut" menjelaskan "#". Pada Bash 4.3.30, 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 .
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}
Sampai saya datang ke teladan Anda, saya telah memahami urutan sebaliknya. Ini membantu memperjelas apa yang terjadi
raghav710
5
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 loveSuzi 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.
Jawaban:
Untuk mengganti kemunculan pertama pola dengan string yang diberikan, gunakan :
${parameter/pattern/string}
Untuk mengganti semua kejadian, gunakan :
${parameter//pattern/string}
(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" .
sumber
\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 inginSTRING//
- ganti semua - bukan hanyaSTRING/
.)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:
Itu hanya akan menggantikan kejadian pertama; untuk mengganti semuanya, gandakan tebasan pertama:
sumber
Untuk Dash semua posting sebelumnya tidak berfungsi
sh
Solusi yang kompatibel dengan POSIX adalah:sumber
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:
sumber
Lebih baik menggunakan bash daripada
sed
jika string memiliki karakter RegExp.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:
Ke dalam ini:
Tetapi hanya jika
/home/name
di awal. Kami tidak butuhsed
!Mengingat bahwa bash memberi kita variabel ajaib
$PWD
dan$HOME
, kita dapat: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 .sumber
sed
denganpwd
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, keluaranuname
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:
Pasti ada 50 cara untuk meninggalkan kekasih Anda.
sumber
Karena saya tidak bisa menambahkan komentar. @ruaka Agar contohnya lebih mudah dibaca, tulis seperti ini
sumber
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:Keluaran:
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.sumber
Saya tahu ini sudah tua tetapi karena tidak ada yang menyebutkan tentang menggunakan awk:
sumber
sumber