ตัวอย่างเช่นกำหนด:
USCAGoleta9311734.5021-120.1287855805
ฉันต้องการแยกเพียง:
US
ตัวอย่างเช่นกำหนด:
USCAGoleta9311734.5021-120.1287855805
ฉันต้องการแยกเพียง:
US
คำตอบ:
อาจเป็นวิธีที่มีประสิทธิภาพที่สุดหากคุณใช้bash
เชลล์ (และดูเหมือนว่าคุณจะอิงตามความคิดเห็นของคุณ) คือการใช้ตัวแปรสตริงย่อยของการขยายพารามิเตอร์:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
สิ่งนี้จะตั้งshort
ให้เป็นอักขระสองตัวแรกของlong
. ถ้าlong
สั้นกว่าสองอักขระshort
จะเหมือนกัน
วิธีการในเชลล์นี้มักจะดีกว่าถ้าคุณจะทำมันเป็นจำนวนมาก (เช่น 50,000 ครั้งต่อรายงานตามที่คุณพูดถึง) เนื่องจากไม่มีค่าใช้จ่ายในการสร้างกระบวนการ โซลูชันทั้งหมดที่ใช้โปรแกรมภายนอกจะได้รับผลกระทบจากค่าใช้จ่ายดังกล่าว
หากคุณต้องการให้แน่ใจว่ามีความยาวขั้นต่ำคุณสามารถรองออกก่อนมือโดยใช้สิ่งต่อไปนี้:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
สิ่งนี้จะช่วยให้มั่นใจได้ว่ามีการเพิ่มอักขระที่มีความยาวน้อยกว่าสองตัวทางด้านขวาพร้อมจุด (หรืออย่างอื่นเพียงแค่เปลี่ยนตัวอักษรที่ใช้ในการสร้างtmpstr
) ไม่ชัดเจนว่าคุณต้องการสิ่งนี้ แต่ฉันคิดว่าฉันจะใส่มันเพื่อความสมบูรณ์
ต้องบอกว่ามีหลายวิธีในการดำเนินการกับโปรแกรมภายนอก (เช่นถ้าคุณไม่มีbash
ให้คุณใช้งาน) ซึ่งบางวิธี ได้แก่ :
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
สองตัวแรก ( cut
และhead
) เหมือนกันสำหรับสตริงบรรทัดเดียว - โดยพื้นฐานแล้วทั้งคู่จะให้อักขระสองตัวแรกแก่คุณ ซึ่งแตกต่างกันตรงที่cut
จะให้อักขระสองตัวแรกของแต่ละบรรทัดและhead
จะให้อักขระสองตัวแรกของอินพุตทั้งหมด
ตัวที่สามใช้awk
ฟังก์ชันสตริงย่อยเพื่อแยกอักขระสองตัวแรกและตัวที่สี่ใช้การsed
จับกลุ่ม (โดยใช้()
และ\1
) เพื่อจับอักขระสองตัวแรกและแทนที่ทั้งบรรทัดด้วย ทั้งคู่คล้ายกับcut
- ส่งอักขระสองตัวแรกของแต่ละบรรทัดในอินพุต
สิ่งนี้ไม่สำคัญหากคุณแน่ใจว่าข้อมูลที่คุณป้อนเป็นบรรทัดเดียวทั้งหมดนี้มีผลเหมือนกัน
printf '%s'
แทนecho
ในกรณีที่มีตัวอักษรแปลกในสตริง: stackoverflow.com/a/40423558/895245สำหรับ POSIX หมกมุ่น: head -c
ไม่ POSIX, cut -c
และawk substr
จะsed \1
ไม่แน่ใจว่า
วิธีที่ง่ายที่สุดคือ
${string:position:length}
โดยที่สิ่งนี้แยก$length
สตริงย่อยจาก$string
ที่$position
.
นี่คือ bash builtin ดังนั้นจึงไม่จำเป็นต้องใช้ awk หรือ sed
คุณได้รับคำตอบที่ดีหลายคนและฉันไปกับทุบตีในตัวเอง แต่เนื่องจากคุณถามเกี่ยวกับsed
และawk
และ ( เกือบโซลูชั่น) ไม่มีใครที่นำเสนอบนพื้นฐานของพวกเขาผมให้คุณเหล่านี้:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
และ
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
สิ่งที่awk
ควรจะชัดเจนพอสมควร แต่นี่คือคำอธิบายsed
:
substr($0,1,2)
.
หากคุณเข้าbash
มาคุณสามารถพูดว่า:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
นี่อาจเป็นเพียงสิ่งที่คุณต้องการ ...
เพียง grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
ตัวเลือกเพื่อทำให้สั้นลงได้ regexs ทั้งหมดจะเข้าใจรูปแบบนั้น
คุณสามารถใช้printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
colrm - ลบคอลัมน์ออกจากไฟล์
หากต้องการเว้นสองตัวอักษรแรกเพียงแค่ลบคอลัมน์ที่เริ่มจาก 3
cat file | colrm 3
ค่อนข้างสาย แต่นี่คือ
sed 's/.//3g'
หรือ
awk NF=1 FPAT=..
หรือ
perl -pe '$_=unpack a2'
หากคุณต้องการใช้เชลล์สคริปต์และไม่พึ่งพาส่วนขยายที่ไม่ใช่ posix (เช่นที่เรียกว่า bashisms) คุณสามารถใช้เทคนิคที่ไม่ต้องใช้เครื่องมือภายนอกเช่น grep, sed, cut, awk เป็นต้น ทำให้สคริปต์ของคุณมีประสิทธิภาพน้อยลง บางทีประสิทธิภาพและความสามารถในการพกพา posix ไม่สำคัญในกรณีการใช้งานของคุณ แต่ในกรณีที่เป็น (หรือเป็นนิสัยที่ดี) คุณสามารถใช้วิธีตัวเลือกการขยายพารามิเตอร์ต่อไปนี้เพื่อแยกอักขระสองตัวแรกของตัวแปรเชลล์:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
ซึ่งใช้การขยายพารามิเตอร์ "คำนำหน้าน้อยที่สุด"เพื่อลบอักขระสองตัวแรก (ซึ่งเป็น${var#??}
ส่วนหนึ่ง) จากนั้นขยายพารามิเตอร์ "คำต่อท้ายที่เล็กที่สุด" ( ${var%
ส่วน) เพื่อลบสตริงอักขระสองตัวทั้งหมด แต่แรกออกจากอักขระดั้งเดิม ความคุ้มค่า
วิธีนี้เคยอธิบายไว้ในคำตอบของคำถาม "Shell = Check ว่าขึ้นต้นด้วย #" หรือไม่ คำตอบนั้นยังอธิบายถึงวิธีการขยายพารามิเตอร์ที่คล้ายกันสองวิธีซึ่งสามารถใช้ในบริบทที่แตกต่างกันเล็กน้อยซึ่งเป็นวิธีที่ใช้กับคำถามเดิมที่นี่
หากระบบของคุณใช้เชลล์อื่น (ไม่ใช่bash
) แต่ระบบของคุณมีbash
คุณยังคงสามารถใช้การจัดการสตริงโดยธรรมชาติได้bash
โดยการเรียกใช้bash
ตัวแปร:
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
bash
หากคุณยังไม่ได้ใช้งานเท่านั้น
เพียงเพื่อความสนุกสนานฉันเพิ่มบางส่วนที่แม้ว่าพวกเขาจะซับซ้อนและไร้ประโยชน์ แต่ก็ไม่ได้กล่าวถึง:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
ถ้า mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
จะพิมพ์เรา
โดยที่ 0 คือตำแหน่งเริ่มต้นและ 2 คือวิธีการอ่านอักขระผู้ชาย
awk
โอ้รอว่า ขอโทษทีแรกบอกไม่ได้
นี่คือสิ่งที่คุณต้องการหรือไม่?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
อ้างอิง: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'