ฉันต้องการระบุตำแหน่งของอักขระในสตริงโดยใช้คำสั่ง 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))