วิธีการรับถ่านที่ตำแหน่งที่กำหนดของสตริงในเชลล์สคริปต์?


คำตอบ:


36

ในทุบตีด้วย "การขยายพารามิเตอร์" $ $ พารามิเตอร์: ชดเชย: ความยาว}

$ var=abcdef
$ echo ${var:0:1}
a
$ echo ${var:3:1}
d

แก้ไข: ไม่ใช้การขยายพารามิเตอร์ (ไม่หรูหรามาก แต่นั่นคือสิ่งที่ฉันมาก่อน)

$ charpos() { pos=$1;shift; echo "$@"|sed 's/^.\{'$pos'\}\(.\).*$/\1/';}
$ charpos 8 what ever here
r

1
gnu.org/software/bash/manual/…มีรายละเอียดเพิ่มเติม
jsbillings


คุณสามารถตั้งค่าออฟเซ็ต 'จากจุดสิ้นสุด' อย่างนั้นได้echo ${var: -2:1}
Vassilis

ไวยากรณ์ที่มาจาก ksh93 และยังได้รับการสนับสนุนโดยและzsh mksh
Stéphane Chazelas

6

ทางเลือกในการขยายพารามิเตอร์คือ expr substr

substr STRING POS LENGTH
    substring of STRING, POS counted from 1

ตัวอย่างเช่น:

$ expr substr hello 2 1
e

เย็นควรตรวจสอบ expr อย่างละเอียดมากขึ้น
forcefsck

1
แม้ว่าสิ่งนี้จะทำงานกับ expr จาก coreutils ของ GNU แต่substrไม่รวมอยู่ใน expr จาก FreeBSD, NetBSD หรือ OS X นี่ไม่ใช่โซลูชันแบบพกพา
ghoti

@ghoti โปรดทราบว่าsubstrเดิมไม่ใช่ส่วนขยาย GNU การใช้งานดั้งเดิมexprมาจาก PWB Unix ในช่วงปลายยุค 70 และมีsubstr(แต่ไม่ใช่:)
Stéphane Chazelas

@ StéphaneChazelasขอบคุณสำหรับการเพิ่มมุมมองทางประวัติศาสตร์ :) ในขณะที่ฉันค่อนข้างมั่นใจว่าการใช้งาน PWB นั้นไม่เกี่ยวข้องกับ OP แต่ก็สนุกกับการติดตามคุณสมบัติและการเปลี่ยนแปลงตลอดหลายทศวรรษ GNU มีแนวโน้มที่จะเป็นค่าเริ่มต้นของหลาย ๆ คน แต่โดยทั่วไปฉันคิดว่าฉันจะหลีกเลี่ยงการใช้ตัวเลือกที่ไม่ชัดเจนPOSIXและเป็นที่รู้กันว่าหายไปจากกลุ่มหลัก
ghoti

5

cut -c

หากตัวแปรไม่มีการขึ้นบรรทัดใหม่คุณสามารถทำได้:

myvar='abc'
printf '%s\n' "$myvar" | cut -c2

เอาท์พุท:

b

awk substr เป็นอีกทางเลือก POSIX ที่ใช้งานได้แม้ว่าตัวแปรจะมีบรรทัดใหม่:

myvar="$(printf 'a\nb\n')" # note that the last newline is stripped by
                           # the command substitution
awk -- 'BEGIN {print substr (ARGV[1], 3, 1)}' "$myvar"

เอาท์พุท:

b

printf '%s\n'คือการหลีกเลี่ยงปัญหาเกี่ยวกับอักขระเลี่ยง: /programming//a/40423558/895245เช่น:

myvar='\n'
printf '%s\n' "$myvar" | cut -c1

ผลผลิต\ตามที่คาดไว้

ดูเพิ่มเติมที่: /programming/1405611/extracting-first-two-characters-of-a-string-shell-scripting

ทดสอบใน Ubuntu 19.04


printf '%s' "$myvar" | cut -c2ไม่ใช่ POSIX เนื่องจากเอาต์พุตของprintfไม่ใช่ข้อความเว้นแต่จะ$myvarลงท้ายด้วยอักขระขึ้นบรรทัดใหม่ มิฉะนั้นจะถือว่าตัวแปรไม่มีอักขระขึ้นบรรทัดใหม่ขณะcutตัดแต่ละบรรทัดของอินพุต
Stéphane Chazelas

awkหนึ่งจะมีประสิทธิภาพมากขึ้นและเชื่อถือได้กับawk -- 'BEGIN {print substr (ARGV[1], 2, 1)}' "$myvar"
Stéphane Chazelas

โปรดทราบว่าด้วย GNU รุ่นปัจจุบันcutที่ใช้งานไม่ได้กับอักขระแบบหลายไบต์ (เหมือนกันสำหรับ mawk หรือ busybox awk)
Stéphane Chazelas

@ StéphaneChazelasขอบคุณสำหรับคะแนน ฉันไม่เข้าใจสิ่งที่คุณหมายถึงในแรก: คุณหมายถึงว่าprintf 'abc '| cut -c2ผิดเพราะไม่มี\n(สิ่งนี้ฉันไม่รู้เกี่ยวกับ) หรือว่าคำสั่งจะล้มเหลวถ้า myvar มีบรรทัดใหม่ (ฉันเห็นด้วย)?
Ciro Santilli 新疆改造中心法轮功六四事件

1
ลักษณะการทำงานของcutไม่ได้รับการระบุหากอินพุตไม่ใช่ข้อความ (แม้ว่าcutการใช้งานจะต้องมีการจัดการกับเส้นหรือความยาวโดยพลการ) ผลลัพธ์ของprintf abcไม่ใช่ข้อความเนื่องจากไม่ได้ลงท้ายด้วยอักขระบรรทัดใหม่ ในทางปฏิบัติขึ้นอยู่กับการดำเนินการถ้าคุณท่อที่cut -c2คุณจะได้รับอย่างใดอย่างหนึ่งb, b<newline>หรืออะไรเลย คุณจะต้องprintf 'abc\n' | cut -c2ได้รับพฤติกรรมที่ระบุโดย POSIX (ที่จำเป็นในการส่งออกb<newline>)
Stéphane Chazelas

1

ด้วยzshหรือyashคุณจะใช้:

$ text='€$*₭£'
$ printf '%s\n' "${text[3]}"
*

(ในzshคุณสามารถย่อให้สั้นลงprintf '%s\n' $text[3])


0

คุณสามารถใช้คำสั่งตัด วิธีรับตำแหน่งที่ 3:

echo "SAMPLETEXT" | cut -c3

ตรวจสอบลิงค์นี้ได้ที่http://www.folkstalk.com/2012/02/cut-command-in-unix-linux-examples.html

( กรณีขั้นสูง ) อย่างไรก็ตามการแก้ไข IFS ก็เป็นสิ่งที่ดีเช่นกันโดยเฉพาะเมื่ออินพุตของคุณอาจมีช่องว่าง ในกรณีนั้นเพียงอย่างเดียวให้ใช้อันด้านล่าง

saveifs=$IFS
IFS=$(echo -en "\n\b")
echo "SAMPLETEXT" | cut -c3
IFS=$saveifs

ฉันไม่เห็นว่าIFSจะเกิดอะไรขึ้นกับรหัสที่คุณโพสต์
Kusalananda
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.