ฉันมี "ฉันรัก Suzi และ Marry" และฉันต้องการเปลี่ยน "Suzi" เป็น "Sara"
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
ผลลัพธ์จะต้องเป็นดังนี้:
firstString="I love Sara and Marry"ฉันมี "ฉันรัก Suzi และ Marry" และฉันต้องการเปลี่ยน "Suzi" เป็น "Sara"
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
# do something...
ผลลัพธ์จะต้องเป็นดังนี้:
firstString="I love Sara and Marry"คำตอบ:
ในการแทนที่การเกิดขึ้นครั้งแรกของรูปแบบด้วยสตริงที่กำหนดให้ใช้:${parameter/pattern/string}
#!/bin/bash
firstString="I love Suzi and Marry"
secondString="Sara"
echo "${firstString/Suzi/$secondString}"    
# prints 'I love Sara and Marry'
หากต้องการแทนที่เหตุการณ์ทั้งหมดให้ใช้:${parameter//pattern/string}
message='The secret code is 12345'
echo "${message//[0-9]/X}"           
# prints 'The secret code is XXXXX'
(นี่คือการบันทึกไว้ในคู่มือทุบตีอ้างอิง , §3.5.3 "ขยายเชลล์พารามิเตอร์" .)
โปรดทราบว่า POSIX ไม่ได้ระบุคุณสมบัตินี้ - เป็นส่วนขยาย Bash - ดังนั้นเชลล์ Unix ทั้งหมดจึงไม่สามารถใช้งานได้ สำหรับเอกสารที่เกี่ยวข้อง POSIX ดูเปิด Group ฐานมาตรฐานข้อมูลจำเพาะทางเทคนิค, ฉบับที่ 7ที่เชลล์และสาธารณูปโภคปริมาณ§2.6.2 "การขยายตัวพารามิเตอร์"
\nในบริบทนั้นจะเป็นตัวแทนของตัวเองไม่ใช่ขึ้นบรรทัดใหม่ ตอนนี้ฉันไม่มี Bash ที่สะดวกในการทดสอบ แต่คุณควรจะเขียนอะไรบางอย่างเช่น$STRING="${STRING/$'\n'/<br />}". (แม้ว่าคุณอาจต้องการSTRING//- แทนที่ทั้งหมด - แทนที่จะเป็นเพียงSTRING/)
                    echo ${my string foo/foo/bar}คุณไม่สามารถทำ คุณต้องการinput="my string foo"; echo ${input/foo/bar}
                    //โดยตรงมันกล่าวถึงสิ่งที่เกิดขึ้น "ถ้ารูปแบบเริ่มต้นด้วย ' /'" (ซึ่งไม่แม่นยำแม้แต่เนื่องจากส่วนที่เหลือของประโยคนั้นถือว่าเป็นพิเศษ/ไม่ใช่ส่วนหนึ่งของ รูปแบบ) - แต่ฉันไม่รู้แหล่งที่ดีกว่านี้
                    สามารถทำได้ทั้งหมดด้วยการจัดการสตริงทุบตี:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
สิ่งนั้นจะเข้ามาแทนที่เหตุการณ์แรกเท่านั้น หากต้องการแทนที่ทั้งหมดให้เพิ่มเครื่องหมายทับแรกเป็นสองเท่า:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}
# first is now "Sara, Sara, Sara"
สำหรับ Dash โพสต์ก่อนหน้าทั้งหมดไม่ทำงาน
shโซลูชันที่รองรับPOSIX คือ:
result=$(echo "$firstString" | sed "s/Suzi/$secondString/")result=$(echo $firstString | sed "s/Suzi/$secondString/g")
                    echoอาร์กิวเมนต์ มันสามารถใช้งานได้โดยไม่ต้องพูดถึงกับสตริงที่เรียบง่าย แต่สามารถแยกสตริงอินพุตที่ไม่ใช่เรื่องง่าย (เว้นวรรคผิดปกติเชลล์เมตาอักขระ)
                    ลองนี้:
 sed "s/Suzi/$secondString/g" <<<"$firstString"จะดีกว่าsedถ้าใช้ bash มากกว่าถ้าสตริงมีอักขระ RegExp
echo ${first_string/Suzi/$second_string}มันเป็นแบบพกพาไปยัง Windows และใช้งานได้กับ Bash 3.1 เป็นอย่างน้อย
เพื่อแสดงว่าคุณไม่ต้องกังวลกับการหลบหนีลองทำสิ่งนี้:
/home/name/foo/barเป็นนี้
~/foo/barแต่ถ้า/home/nameเป็นเพียงในการเริ่มต้น เราไม่ต้องการsed!
เนื่องจาก bash นั้นทำให้เรามีตัวแปรเวทย์มนตร์$PWDและ$HOMEเราสามารถ:
echo "${PWD/#$HOME/\~}"แก้ไข:ขอบคุณสำหรับ Mark Haferkamp ในความคิดเห็นเพื่อทราบเกี่ยวกับการอ้างอิง / หลบหนี~*
สังเกตว่าตัวแปร$HOMEมีเครื่องหมายสแลช แต่สิ่งนี้ไม่ทำลายอะไร
อ่านเพิ่มเติม: ขั้นสูงทุบตี Scripting คู่มือ 
ถ้าใช้sedเป็นต้องให้แน่ใจว่าได้หลบหนีตัวละครทุกตัว
sedกับpwdคำสั่งเพื่อหลีกเลี่ยงการกำหนดตัวแปรใหม่ทุกครั้งที่กำหนดเองของฉัน$PS1ทำงาน Bash มีวิธีทั่วไปมากกว่าตัวแปรเวทเพื่อใช้เอาต์พุตของคำสั่งสำหรับการแทนที่สตริงหรือไม่? สำหรับโค้ดของคุณฉันต้องหลบเลี่ยง~เพื่อป้องกัน Bash ไม่ให้ขยายเป็น $ HOME นอกจากนี้สิ่งที่#อยู่ในคำสั่งของคุณจะทำอย่างไร
                    ~": สังเกตว่าฉันอ้างถึงสิ่งต่างๆอย่างไร จำไว้ว่าให้พูดทุกสิ่ง! และสิ่งนี้ไม่เพียงทำงานให้กับตัวแปรเวทย์มนตร์เท่านั้น: ตัวแปรใด ๆ ก็ตามที่สามารถทดแทนได้รับความยาวสตริงและอื่น ๆ อีกมากภายในการทุบตี ขอแสดงความยินดีที่คุณพยายาม$PS1อย่างรวดเร็ว: คุณอาจสนใจ$PROMPT_COMMANDถ้าคุณคุ้นเคยกับภาษาการเขียนโปรแกรมอื่นและต้องการรหัสที่คอมไพล์แล้ว
                    echo "${PWD/#$HOME/~}"ไม่ได้แทนฉันด้วย$HOME ~แทนที่~ด้วย\~หรือ'~'ทำงาน งานใด ๆ เหล่านี้ใน Bash 4.2.53 ใน distro อื่น คุณช่วยอัพเดทโพสต์ของคุณเพื่ออ้างหรือหลีกเลี่ยง~เพื่อความเข้ากันได้ที่ดีขึ้นหรือไม่? สิ่งที่ฉันหมายถึงโดยคำถาม "ตัวแปรวิเศษ" ของฉันคือ: ฉันสามารถใช้การแทนที่ตัวแปรของ Bash เช่นผลลัพธ์ของunameโดยไม่บันทึกเป็นตัวแปรเป็นอันดับแรกได้หรือไม่ ในฐานะที่เป็นส่วนบุคคลของฉัน$PROMPT_COMMAND, มันซับซ้อน 
                    ถ้าพรุ่งนี้คุณตัดสินใจว่าคุณไม่รักมารีรี่ย์เธอก็สามารถถูกแทนที่ด้วยเช่นกัน:
today=$(</tmp/lovers.txt)
tomorrow="${today//Suzi/Sara}"
echo "${tomorrow//Marry/Jesica}" > /tmp/lovers.txtจะต้องมี 50 วิธีในการละทิ้งคู่รักของคุณ
เนื่องจากฉันไม่สามารถเพิ่มความคิดเห็น @ruaka เพื่อให้ตัวอย่างอ่านง่ายขึ้นเขียนเช่นนี้
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}เพียวPOSIXวิธีเปลือกซึ่งแตกต่างจากโรมัน Kazanovskyi 's sedคำตอบชั่นไม่จำเป็นต้องเครื่องมือภายนอกเพียงเปลือกของตัวเองพื้นเมืองขยายพารามิเตอร์ โปรดทราบว่าชื่อไฟล์แบบยาวจะย่อเล็กสุดเพื่อให้โค้ดพอดีกับหนึ่งบรรทัด:
f="I love Suzi and Marry"
s=Sara
t=Suzi
[ "${f%$t*}" != "$f" ] && f="${f%$t*}$s${f#*$t}"
echo "$f"เอาท์พุท:
I love Sara and Marryมันทำงานอย่างไร:
ลบรูปแบบคำต่อท้ายที่เล็กที่สุด  "${f%$t*}"ส่งคืน " I love" ถ้าส่วนต่อท้าย$t" Suzi*" อยู่ใน$f" "  I love Suzi and Marry
แต่ถ้าถ้าt=Zeldaเช่นนั้น"${f%$t*}"จะไม่ลบอะไรเลยและส่งคืนสตริงทั้งหมด " I love Suzi and Marry"
ใช้เพื่อทดสอบว่า$tมีการ$fใช้งาน[ "${f%$t*}" != "$f" ]ซึ่งจะประเมินเป็นจริงหาก$fสตริงมี " Suzi*" และเท็จถ้าไม่
หากการทดสอบส่งคืนค่าจริงสร้างสตริงที่ต้องการโดยใช้Remove Smallest Suffix Pattern ${f%$t*} " I love" และRemove Smallest Prefix Pattern ${f#*$t} " and Marry" โดยมีสตริงที่2$s " Sara" อยู่ระหว่างนั้น
ฉันรู้ว่ามันเก่า แต่เนื่องจากไม่มีใครพูดถึงการใช้ awk:
    firstString="I love Suzi and Marry"
    echo $firstString | awk '{gsub("Suzi","Sara"); print}'echo [string] | sed "s/[original]/[target]/g"