ในbashสคริปต์ของฉันฉันมีสตริงและคำนำหน้า / คำต่อท้าย ฉันต้องการลบคำนำหน้า / คำต่อท้ายจากสตริงเดิม
ตัวอย่างเช่นสมมติว่าฉันมีค่าต่อไปนี้:
string="hello-world"
prefix="hell"
suffix="ld"
ฉันจะรับผลลัพธ์ต่อไปนี้ได้อย่างไร
result="o-wor"
ในbashสคริปต์ของฉันฉันมีสตริงและคำนำหน้า / คำต่อท้าย ฉันต้องการลบคำนำหน้า / คำต่อท้ายจากสตริงเดิม
ตัวอย่างเช่นสมมติว่าฉันมีค่าต่อไปนี้:
string="hello-world"
prefix="hell"
suffix="ld"
ฉันจะรับผลลัพธ์ต่อไปนี้ได้อย่างไร
result="o-wor"
คำตอบ:
$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor
${${string#prefix}%suffix}แต่มันใช้งานไม่ได้
ใช้ sed:
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor
ภายในคำสั่ง sed ที่^ตัวละครตรงกับจุดเริ่มต้นข้อความด้วย$prefixและต่อท้ายตรงกับข้อความที่ลงท้ายด้วย$$suffix
Adrian Frühwirthให้คะแนนที่ดีในความคิดเห็นด้านล่าง แต่sedสำหรับจุดประสงค์นี้อาจมีประโยชน์มาก ความจริงที่ว่าเนื้อหาของ $ prefix และ $ suffix ถูกตีความโดย sed อาจเป็นได้ทั้งดีหรือไม่ดีตราบใดที่คุณให้ความสนใจคุณก็ควรจะปรับ ความงามคือคุณสามารถทำสิ่งนี้:
$ prefix='^.*ll'
$ suffix='ld$'
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor
ซึ่งอาจเป็นสิ่งที่คุณต้องการและมีทั้งนักเล่นและมีประสิทธิภาพมากกว่าการแทนที่ตัวแปร bash หากคุณจำได้ว่ามีพลังอันยิ่งใหญ่มาพร้อมความรับผิดชอบที่ดี (ตามที่ Spiderman พูด) คุณควรจะสบายดี
คำแนะนำเบื้องต้นเกี่ยวกับ sed สามารถดูได้ที่http://evc-cit.info/cit052/sed_tutorial.html
หมายเหตุเกี่ยวกับเชลล์และการใช้สตริง:
สำหรับตัวอย่างที่ระบุไว้ต่อไปนี้จะทำงานได้เช่นกัน:
$ echo $string | sed -e s/^$prefix// -e s/$suffix$//
... แต่เพียงเพราะ:
เป็นแนวปฏิบัติที่ดีในการอ้างอิงสตริงในบรรทัดคำสั่งเพราะแม้ว่าจะมีช่องว่างมันจะถูกนำเสนอให้กับคำสั่งเป็นอาร์กิวเมนต์เดียว เราอ้างอิง $ prefix และ $ suffix ด้วยเหตุผลเดียวกัน: แต่ละคำสั่ง edit เพื่อ sed จะถูกส่งเป็นสตริงเดียว เราใช้เครื่องหมายคำพูดคู่เพราะอนุญาตสำหรับการแก้ไขตัวแปร ถ้าเราใช้เครื่องหมายคำพูดเดี่ยวคำสั่ง sed จะได้รับตัวอักษร$prefixและ$suffixซึ่งแน่นอนว่าไม่ใช่สิ่งที่เราต้องการ
แจ้งให้ทราบล่วงหน้าเกินไปใช้งานของฉันราคาเดียวเมื่อตั้งค่าตัวแปรและprefix suffixแน่นอนว่าเราไม่ต้องการอะไรที่จะตีความดังนั้นเราจึงอ้างถึงมันเพื่อไม่ให้เกิดการแก้ไข อีกครั้งอาจไม่จำเป็นในตัวอย่างนี้ แต่เป็นนิสัยที่ดีในการเข้า
$stringกล่าวถึง 2) $prefixและ$suffixสามารถมีการแสดงออกที่sedจะตีความเช่นการแสดงออกปกติหรือตัวละครที่ใช้เป็นตัวคั่นที่จะทำลายคำสั่งทั้งหมด 3) sedไม่จำเป็นต้องโทรสองครั้ง (คุณสามารถ-e 's///' -e '///'แทนได้) และสามารถหลีกเลี่ยงท่อได้ ตัวอย่างเช่นพิจารณาstring='./ *'และ / หรือprefix='./'และเห็นมันทำลายอย่างน่ากลัวเนื่องจากการและ1) 2)
/ดังนั้นฉันใช้sed "s#^$prefix##แทน (ความเปราะบาง: ชื่อไฟล์ไม่สามารถมี#ได้เนื่องจากฉันควบคุมไฟล์เราจึงปลอดภัยที่นั่น)
#เป็นตัวคั่นของ sed หมายความว่าคุณไม่สามารถจัดการไฟล์ที่มีตัวอักษรนั้นได้
คุณรู้ความยาวของคำนำหน้าและคำต่อท้ายของคุณหรือไม่? ในกรณีของคุณ:
result=$(echo $string | cut -c5- | rev | cut -c3- | rev)
หรือมากกว่าทั่วไป:
result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev)
แต่ทางออกจาก Adrian Frühwirthนั้นช่างยอดเยี่ยม! ฉันไม่รู้เกี่ยวกับสิ่งนั้น!
ฉันใช้ grep สำหรับการลบคำนำหน้าจากเส้นทาง (ซึ่งไม่ได้รับการจัดการอย่างดีsed):
echo "$input" | grep -oP "^$prefix\K.*"
\K ลบออกจากการจับคู่ตัวละครทั้งหมดก่อนที่จะ
grep -Pเป็นส่วนขยายที่ไม่เป็นมาตรฐาน มีพลังมากขึ้นสำหรับคุณถ้ามันรองรับแพลตฟอร์มของคุณ แต่นี่เป็นคำแนะนำที่น่าสงสัยหากรหัสของคุณต้องพกพาได้อย่างสมเหตุสมผล
grepGNU เวอร์ชันก่อนหน้ามี-Pตัวเลือกจาก BSD จริง ๆgrepแต่มีการลบออก
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ #remove "hell" from "hello-world" if "hell" is found at the beginning.
$ prefix_removed_string=${string/#$prefix}
$ #remove "ld" from "o-world" if "ld" is found at the end.
$ suffix_removed_String=${prefix_removed_string/%$suffix}
$ echo $suffix_removed_String
o-wor
# $ prefix: การเพิ่ม # ทำให้แน่ใจว่าจะลบสตริงย่อย "hell" เฉพาะเมื่อพบในตอนเริ่มต้นเท่านั้น % $ คำต่อท้าย: การเพิ่ม% ทำให้แน่ใจว่าจะลบสตริงย่อย "ld" เฉพาะเมื่อพบในตอนท้าย
หากไม่มีสิ่งเหล่านี้สตริงย่อย "นรก" และ "ld" จะถูกลบออกไปทุกที่แม้จะอยู่ตรงกลาง
/ตรงข้างหลังสตริงสิ่งนั้นมีไว้เพื่ออะไร?
ใช้ตัว=~ดำเนินการ :
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ [[ "$string" =~ ^$prefix(.*)$suffix$ ]] && echo "${BASH_REMATCH[1]}"
o-wor
โซลูชันขนาดเล็กและสากล:
expr "$string" : "$prefix\(.*\)$suffix"
exprเลย มันเป็นความเรียงลำดับของห้องครัวที่สะดวกสาธารณูปโภคอ่างล้างจานกลับมาในวันที่ของเดิม Bourne เปลือก แต่ตอนนี้วิธีที่ดีที่สุดที่ผ่านมาก่อนวันที่
ใช้คำตอบ @Adrian Frühwirth:
function strip {
local STRING=${1#$"$2"}
echo ${STRING%$"$2"}
}
ใช้มันแบบนี้
HELLO=":hello:"
HELLO=$(strip "$HELLO" ":")
echo $HELLO # hello
ฉันจะใช้ประโยชน์จากกลุ่มการจับภาพใน regex:
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ set +H # Disables history substitution, can be omitted in scripts.
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}/\1/" <<< $string
o-wor
$ string1=$string$string
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}/\1/g" <<< $string1
o-woro-wor
((?:(?!(${suffix})).)*)ทำให้แน่ใจว่าเนื้อหาของ${suffix}จะถูกแยกออกจากกลุ่มการดักจับ [^A-Z]*ในแง่ของการเช่นนั้นเทียบเท่าสตริง มิฉะนั้นคุณจะได้รับ:
$ perl -pe "s/${prefix}(.*)${suffix}/\1/g" <<< $string1
o-worldhello-wor