ฉันต้องการระบุตำแหน่งของอักขระในสตริงโดยใช้คำสั่ง grep
RAMSITALSKHMAN|1223333ตัวอย่างเช่นสตริง
grep -n '[^a-zA-Z0-9\$\~\%\#\^]'
ฉันจะค้นหาตำแหน่งของ|ในสตริงที่กำหนดได้อย่างไร
ฉันต้องการระบุตำแหน่งของอักขระในสตริงโดยใช้คำสั่ง grep
RAMSITALSKHMAN|1223333ตัวอย่างเช่นสตริง
grep -n '[^a-zA-Z0-9\$\~\%\#\^]'
ฉันจะค้นหาตำแหน่งของ|ในสตริงที่กำหนดได้อย่างไร
คำตอบ:
คุณสามารถใช้-bเพื่อรับไบต์ออฟเซ็ตซึ่งเป็นตำแหน่งเดียวกันกับข้อความแบบง่าย (แต่ไม่ใช่สำหรับ UTF-8 หรือคล้ายกัน)
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|'
14:|
ในข้างต้นฉันใช้-aสวิตช์บอก grep เพื่อใช้อินพุตเป็นข้อความ จำเป็นเมื่อใช้งานกับไฟล์ไบนารีและ-oสวิตช์เพื่อส่งออกเฉพาะอักขระที่ตรงกัน
หากคุณต้องการตำแหน่งเท่านั้นคุณสามารถใช้ grep เพื่อแยกตำแหน่งเท่านั้น:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' | grep -oE '[0-9]+'
14
หากคุณได้รับผลลัพธ์ที่แปลกตรวจสอบเพื่อดูว่า grep มีการเปิดใช้งานสี คุณสามารถปิดการใช้งานสีได้โดยส่งผ่าน--colors=neverไปยัง grep หรือโดยนำหน้าคำสั่ง grep ด้วย\(ซึ่งจะปิดใช้งานนามแฝงใด ๆ ) เช่น:
$ echo "RAMSITALSKHMAN|1223333" | grep -aob '|' --color=never | \grep -oE '^[0-9]+'
14
สำหรับสตริงที่ส่งคืนการจับคู่หลาย ๆ ไพพ์head -n1ให้ผ่านเพื่อให้ได้แมตช์แรก
โปรดทราบว่าฉันใช้ทั้งในข้างต้นและทราบว่าหลังจะไม่ทำงานหาก grep คือ "aliased" ผ่านการปฏิบัติการ (สคริปต์หรืออย่างอื่น) เฉพาะเมื่อใช้นามแฝง
2;)
^:)
0:|ผลลัพธ์เป็น - เพราะ 0 คือตำแหน่งไบต์ของจุดเริ่มต้นของบรรทัดที่|พบ
grep (GNU grep) 2.27ยืด: คุณอาจใช้ OS X อยู่หรือเปล่า?
ลอง:
printf '%s\n' 'RAMSITALSKHMAN|1223333.' | grep -o . | grep -n '|'
เอาท์พุท:
15:|
สิ่งนี้จะทำให้คุณอยู่ในตำแหน่งที่มีดัชนีอิง -1
printf '%s\n' '|' | grep -o . | grep -n '|'พิมพ์1ไม่0เป็นไปตามที่คาดไว้
หากคุณใช้bash shell คุณสามารถใช้การดำเนินการในตัวโดยไม่จำเป็นต้องวางไข่กระบวนการภายนอกเช่นgrepหรือawk :
$ str="RAMSITALSKHMAN|1223333"
$ tmp="${str%%|*}"
$ if [ "$tmp" != "$str" ]; then
> echo ${#tmp}
> fi
14
$
ใช้การขยายพารามิเตอร์เพื่อลบการเกิดขึ้นทั้งหมด|ตามด้วยสตริงใด ๆ และบันทึกไว้ในตัวแปรชั่วคราว |แล้วมันเป็นเพียงเรื่องของการวัดความยาวของตัวแปรชั่วคราวที่จะได้รับดัชนีของ
สังเกตว่าifกำลังตรวจสอบว่า|มีอยู่ในสตริงเดิมหรือไม่ หากไม่เป็นเช่นนั้นตัวแปรชั่วคราวจะเหมือนกับของเดิม
หมายเหตุนอกจากนี้ยังมีดัชนี zero-based |ซึ่งโดยทั่วไปมีประโยชน์เมื่อทำดัชนีสตริง bash อย่างไรก็ตามหากคุณต้องการดัชนีแบบอิงพื้นฐานคุณสามารถทำสิ่งนี้ได้:
$ echo $((${#tmp}+1))
15
$
คุณสามารถใช้indexฟังก์ชั่นawk เพื่อส่งคืนตำแหน่งในตัวละครที่เกิดการแข่งขันขึ้น:
echo "RAMSITALSKHMAN|1223333"|awk 'END{print index($0,"|")}'
15
หากคุณไม่สนใจการใช้indexฟังก์ชั่นของ Perl สิ่งนี้จะจัดการกับการรายงานศูนย์หนึ่งหรือหลายตัวละคร:
echo "|abc|xyz|123456|zzz|" | \
perl -nle '$pos=-1;while (($off=index($_,"|",$pos))>=0) {print $off;$pos=$off+1}'
เพื่อความสะดวกในการอ่านเท่านั้นท่อส่งได้ถูกแบ่งข้ามสองบรรทัด
ตราบเท่าที่พบอักขระเป้าหมายให้indexส่งคืนค่าบวกตามศูนย์ (0) ดังนั้นสตริง "abc | xyz | 123456 | zzz |" เมื่อแยกวิเคราะห์ส่งคืนตำแหน่ง 0, 4, 8, 15 และ 19
RAMSITALSKHMAN|1|223333
นอกจากนี้เรายังสามารถทำได้โดยใช้ "การจับคู่ expr" หรือ "ดัชนี expr"
expr จับคู่ $ string $ substring โดยที่ $ substring เป็น RE
echo `expr match "RAMSITALSKHMAN|1223333" '[A-Z]*.|'`
และด้านบนจะให้ตำแหน่งเนื่องจากจะส่งคืนความยาวของสตริงย่อยที่ตรงกัน
แต่จะเฉพาะเจาะจงมากขึ้นสำหรับการค้นหาดัชนี:
mystring="RAMSITALSKHMAN|122333"
echo `expr index "$mystring" '|'`
awkโซลูชั่นสามารถแก้ไขได้เล็กน้อยสำหรับรายงานข้อมูลนี้ในทุกบรรทัดของไฟล์ (สิ่งที่คุณต้องทำคือลบสิ่งENDที่ไม่จำเป็นจริงๆออกจากคำตอบของ JRFerguson และ Avinash Raj ก็ทำได้แล้ว) ; ในขณะที่จะทำอย่างนั้นกับexprวิธีการแก้ปัญหาที่คุณจะต้องเพิ่มห่วงอย่างชัดเจน (และคำตอบ Gnouc ไม่ได้ปรับตัวได้ง่ายที่จะทำทั้งหมดที่ฉันสามารถดู) และ (2) awkการแก้ปัญหาที่สามารถปรับให้รายงานทั้งหมด การจับคู่ในแต่ละบรรทัดค่อนข้างง่ายกว่าการexprแก้ปัญหา (อันที่จริง Avinash Raj ก็ทำเช่นนั้นด้วย)
echo `...`ที่นี่?
$ echo 'RAMSITALSKHMAN|1223333'| awk 'BEGIN{ FS = "" }{for(i=1;i<=NF;i++){if($i=="|"){print i;}}}'
15
โดยการตั้งค่าตัวคั่นฟิลด์เป็นสตริง null awk เปลี่ยนอักขระแต่ละตัวในบันทึกเป็นฟิลด์แยก
ทางเลือกบางอย่างรวมถึง:
คล้ายกับคำตอบของ Gnouc แต่ใช้กระสุน:
echo 'RAMSITALSKHMAN|1223333' |
tr -c \| \\n |
sh
sh: line 15: syntax error near unexpected token `|
sh: line 15: `|'
ด้วยsedและdcอาจทอดหลายบรรทัด:
echo 'RAMSITALSKHMAN|1223333' |
sed 's/[^|]/1+/g;s/|/p/;1i0 1+' |dc
15
ด้วย$IFS...
IFS=\|; set -f; set -- ${0+RAMSITALSKHMAN|1223333}; echo $((${#1}+1))
นั่นจะบอกคุณว่ามีจำนวนเท่าใด...
echo $(($#-1))