ใน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
เป็นส่วนขยายที่ไม่เป็นมาตรฐาน มีพลังมากขึ้นสำหรับคุณถ้ามันรองรับแพลตฟอร์มของคุณ แต่นี่เป็นคำแนะนำที่น่าสงสัยหากรหัสของคุณต้องพกพาได้อย่างสมเหตุสมผล
grep
GNU เวอร์ชันก่อนหน้ามี-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