สมมติว่าฉันมีสตริง1:2:3:4:5
และฉันต้องการได้รับเขตข้อมูลสุดท้าย ( 5
ในกรณีนี้) ฉันจะทำเช่นนั้นโดยใช้ Bash ได้อย่างไร ฉันพยายามแต่ผมไม่ทราบว่าวิธีการระบุข้อมูลที่ผ่านมาด้วยcut
-f
สมมติว่าฉันมีสตริง1:2:3:4:5
และฉันต้องการได้รับเขตข้อมูลสุดท้าย ( 5
ในกรณีนี้) ฉันจะทำเช่นนั้นโดยใช้ Bash ได้อย่างไร ฉันพยายามแต่ผมไม่ทราบว่าวิธีการระบุข้อมูลที่ผ่านมาด้วยcut
-f
คำตอบ:
คุณสามารถใช้ตัวดำเนินการสตริง :
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
สิ่งนี้จดจ้องทุกอย่างจากด้านหน้าจนถึง ':' อย่างตะกละตะกลาม
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
${foo%:*}
เห็นได้ชัดโดยใช้ #
- ตั้งแต่ต้น %
- จากจุดสิ้นสุด #
, %
- การแข่งขันที่สั้น; ##
, %%
- การแข่งขันที่ยาวที่สุด
echo ${pwd##*/}
ไม่ทำงาน, ไม่เป็นผล.
pwd
ว่าเป็นตัวแปร ลองdir=$(pwd); echo ${dir##*/}
ดู ใช้งานได้สำหรับฉัน!
อีกวิธีหนึ่งคือการย้อนกลับก่อนและหลังcut
:
$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
สิ่งนี้ทำให้ง่ายมากที่จะได้รับฟิลด์สุดท้าย แต่ฟิลด์เดียวหรือช่วงของฟิลด์ใด ๆ ที่มีหมายเลขจากจุดสิ้นสุด
echo "1 2 3 4" | rev | cut -d " " -f1 | rev
rev
มันเป็นสิ่งที่ฉันต้องการ! cut -b20- | rev | cut -b10- | rev
เป็นเรื่องยากที่จะทำให้ฟิลด์สุดท้ายใช้การตัด แต่นี่คือวิธีแก้ปัญหาบางอย่างใน awk และ perl
echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
/
ตัวอักษร: /a/b/c/d
และ/a/b/c/d/
เกิดผลเหมือนกัน ( d
) pwd | awk -F/ '{print $NF}'
เมื่อการประมวลผล คำตอบที่ได้รับการยอมรับส่งผลให้เกิดผลลัพธ์ที่ว่างเปล่าในกรณีของ/a/b/c/d/
/
เป็นตัวคั่นและถ้าเส้นทางของคุณ/my/path/dir/
มันจะใช้ค่าหลังจากตัวคั่นล่าสุดซึ่งเป็นเพียงสตริงที่ว่างเปล่า ดังนั้นจึงเป็นการดีที่สุดที่จะหลีกเลี่ยงการต่อท้ายสแลชหากคุณต้องการทำสิ่งเช่นฉัน
awk '{$NF=""; print $0}' FS=: OFS=:
มักจะทำงานได้ดีพอ
สมมติว่าการใช้งานค่อนข้างง่าย (ตัวอย่างเช่นไม่ใช้ตัวคั่นใด ๆ ) คุณสามารถใช้ grep:
$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
รายละเอียด - ค้นหาอักขระทั้งหมดที่ไม่ใช่ตัวคั่น ([^:]) ที่ท้ายบรรทัด ($) - พิมพ์เฉพาะส่วนที่จับคู่เท่านั้น
ทางเดียว:
var1="1:2:3:4:5"
var2=${var1##*:}
อื่นโดยใช้อาร์เรย์:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}
อีกอันหนึ่งกับอาเรย์:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}
การใช้ Bash (รุ่น> = 3.2) การแสดงออกปกติ:
var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e
tail -1
เพียงแค่ตัวคั่นแปลลงในการขึ้นบรรทัดใหม่และเลือกรายการสุดท้ายด้วย
\n
แต่สำหรับกรณีส่วนใหญ่เป็นวิธีการแก้ปัญหาที่อ่านได้มากที่สุด
การใช้sed
:
$ echo '1:2:3:4:5' | sed 's/.*://' # => 5
$ echo '' | sed 's/.*://' # => (empty)
$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c
$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c
หากฟิลด์สุดท้ายของคุณเป็นอักขระตัวเดียวคุณสามารถทำสิ่งนี้ได้:
a="1:2:3:4:5"
echo ${a: -1}
echo ${a:(-1)}
a
ไม่สุดท้ายฟิลด์
มีคำตอบที่ดีมากมายที่นี่ แต่ฉันยังต้องการแบ่งปันโดยใช้basename :
basename $(echo "a:b:c:d:e" | tr ':' '/')
อย่างไรก็ตามมันจะล้มเหลวถ้ามี '/' อยู่ในสตริงของคุณอยู่แล้วอยู่แล้ว หาก slash / เป็นตัวคั่นของคุณคุณเพียงแค่ต้อง (และควร) ใช้ชื่อฐาน
มันไม่ใช่คำตอบที่ดีที่สุด แต่มันแสดงให้เห็นว่าคุณสร้างสรรค์ได้อย่างไรโดยใช้คำสั่ง bash
ใช้ Bash
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
echo ${!#}
eval echo \$${#}
echo "a:b:c:d:e"|xargs -d : -n1|tail -1
การใช้งานครั้งแรก xargs แยกโดยใช้ ":", - n1 หมายถึงทุกบรรทัดมีเพียงส่วนเดียวจากนั้น pring ส่วนสุดท้าย
for x in `echo $str | tr ";" "\n"`; do echo $x; done
สำหรับผู้ที่พอใจกับ Python https://github.com/Russell91/pythonpyเป็นทางเลือกที่ดีในการแก้ปัญหานี้
$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'
จากความช่วยเหลือ pythonpy -x treat each row of stdin as x
นี้:
ด้วยเครื่องมือนั้นมันเป็นเรื่องง่ายที่จะเขียนโค้ดไพ ธ อนที่นำไปใช้กับอินพุต
อาจจะช้าไปหน่อยกับคำตอบ แต่วิธีง่ายๆคือการกลับลำดับของสตริงอินพุต สิ่งนี้จะช่วยให้คุณได้รับไอเท็มสุดท้ายไม่ว่าจะยาวแค่ไหน
[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5
มันเป็นสิ่งสำคัญที่จะต้องทราบว่าถ้าใช้วิธีนี้และตัวเลขที่มีขนาดใหญ่กว่า 1 หลัก (หรือมากกว่าหนึ่งตัวอักษรในทุกสถานการณ์) คุณจะต้องเรียกใช้คำสั่ง 'rev' อีกครั้งผ่านเอาต์พุตแบบไพพ์
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24
หวังว่าฉันสามารถช่วยได้ไชโย
วิธีการแก้ปัญหาโดยใช้ read builtin:
IFS=':' read -a fields <<< "1:2:3:4:5"
echo "${fields[4]}"
หรือเพื่อให้ทั่วไปมากขึ้น:
echo "${fields[-1]}" # prints the last item
ถ้าคุณชอบงูใหญ่และมีตัวเลือกในการติดตั้งแพ็คเกจคุณสามารถใช้ยูทิลิตี้หลามนี้ได้
# install pythonp
pythonp -m pip install pythonp
echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5
echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
pythonp
แพ็คเกจคือการทำให้คุณทำสิ่งเดียวpython -c
กับที่มีการพิมพ์ตัวอักษรน้อยลง โปรดดู README ในที่เก็บ
การจับคู่ Regex sed
เป็นโลภมาก (มักจะเกิดขึ้นครั้งล่าสุด) ซึ่งคุณสามารถใช้เพื่อประโยชน์ของคุณที่นี่:
$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
5
เช่นกันหากสตริงคือ1:2:3:4:5:
(ในขณะที่ใช้ตัวดำเนินการสตริงจะให้ผลลัพธ์ที่ว่างเปล่า) สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อแยกวิเคราะห์เส้นทางที่อาจมี (หรือไม่)/
อักขระสิ้นสุด