ฉันจะพิมพ์หมายเลขที่ยาวที่สุดในสตริงได้อย่างไร


11

ฉันกำลังมองหาวิธีการพิมพ์จำนวนที่ยาวที่สุดในสตริง

เช่น: ถ้าฉันมีสตริง

212334123434test233

ฉันจะพิมพ์ได้อย่างไร

212334123434

?

หมายเหตุ: ฉันกำลังมองหาลำดับที่ต่อเนื่องยาวนานที่สุดของตัวเลขไม่ใช่ค่าที่สูงกว่าเป็นตัวเลข


แก้ไข:ขอบคุณสำหรับคำตอบทุกคน การตอบคำถามนี้ค่อนข้างท่วมท้น ฉันทำเครื่องหมายโพสต์ของ @ HaukeLaging เป็นคำตอบที่ยอมรับได้เพราะมันเหมาะกับกรณีของฉันเป็นอย่างดี แต่ฉันต้องการชี้ให้เห็นว่าคำตอบทั้งหมดนั้นใช้ได้อย่างเท่าเทียมกัน เป็นเรื่องที่ดีเสมอที่จะมีตัวเลือกต่าง ๆ เพื่อแก้ไขปัญหา


คุณต้องการให้วิธีการทำอย่างไรเมื่อมีลำดับที่ต่อเนื่องหลาย ๆ อันที่ยาวเท่ากัน? เป็นคนแรกไหม สุดท้าย? แบบสุ่มหรือไม่
Anthon

@ อันธพาลฉันไม่ได้คิดอย่างนั้น โชคดีที่นั่นไม่ใช่ปัญหาในกรณีเฉพาะของฉัน ฉันเดาว่าตัวเลือกใด ๆ จะดี
Glutanimate

3
โปรดทราบว่าคำตอบที่คุณตอบรับ (และอื่น ๆ ทั้งหมดยกเว้นเพียงข้อเดียว ) จะไม่จัดการกับจำนวนทศนิยม ฉันไม่รู้ว่านั่นเป็นปัญหาสำหรับคุณหรือไม่
terdon

@terdon: มันไม่ใช่ปัญหาในกรณีเฉพาะของฉันเพราะฉันกำลังจัดการกับ ID แทนที่จะเป็นตัวเลขจริง แต่ฉันอยากจะขอบคุณสำหรับคำตอบของคุณอย่างไรก็ตาม! ฉันแน่ใจว่าคนอื่นจะพบว่ามีประโยชน์มากในอนาคต
Glutanimate

คุณต้องการวิธีการในการจัดการกับจำนวนลบหรือไม่? และถ้าเป็นเช่นนั้น - เครื่องหมายลบจะนับรวมตามความยาวหรือไม่?
Floris

คำตอบ:



13

ผมเชื่อว่าคุณสามารถทำเช่นนี้มีเพียงgrep, sortและtailเช่นกัน นี่คือตัวอย่างสตริง

$ echo <str> | grep -oP "\d+" | sort -n | tail -1

<str>สตริงของเราอยู่ที่ไหนภายใต้คำถาม

ตัวอย่าง

$ set -o posix; set | grep "str[0-9]"
str0=212334123434test233
str1=212334123434test233abc44
str2=233test212334123434
str3=a212334123434test233abc44
str4=a91234b212334123434abc

ตอนนี้ถ้าฉันเรียกใช้เหล่านี้ผ่านgrep ...คำสั่งของฉันในทางกลับกัน

$ echo $str0 | grep -oP "\d+" | sort -n | tail -1
212334123434
$ echo $str1 | grep -oP "\d+" | sort -n | tail -1
212334123434
$ echo $str2 | grep -oP "\d+" | sort -n | tail -1
212334123434
$ echo $str3 | grep -oP "\d+" | sort -n | tail -1
212334123434
$ echo $str4 | grep -oP "\d+" | sort -n | tail -1
212334123434

วิธีการนี้ใช้งานได้โดยเลือกสตริงย่อยทั้งหมดที่เป็นลำดับของตัวเลข จากนั้นเราจะเรียงลำดับผลลัพธ์นี้ตัวเลขแล้วคว้าค่าสุดท้ายในรายการที่ใช้sort -n tail -1นี่จะเป็นสตริงย่อยที่ยาวที่สุด

คุณสามารถดูวิธีการทำงานได้โดยtail -1ถอดและทำซ้ำตัวอย่างใดตัวอย่างหนึ่ง:

$ echo $str4 | grep -oP "\d+" | sort -n
91234
212334123434

สตริงที่ขึ้นต้นด้วยศูนย์

วิธีการข้างต้นใช้ได้กับทุกสถานการณ์ที่ฉันสามารถนึกได้ยกเว้นเพียงข้อเดียว @terdon พูดถึงในการแชทสถานการณ์นี้ซึ่งเกียดแนวทางข้างต้น

  • 0000000000001
  • 2

ดังนั้นเพื่อรับมือกับสิ่งนี้คุณจะต้องเปลี่ยนยุทธวิธีเล็กน้อย เคอร์เนลของวิธีการข้างต้นยังคงสามารถใช้ประโยชน์ได้อย่างไรก็ตามเราจำเป็นต้องฉีดจำนวนอักขระลงในผลลัพธ์ด้วย สิ่งนี้ทำให้การเรียงลำดับความสามารถในการเรียงลำดับผลลัพธ์ตามจำนวนอักขระในสตริง & ค่าของพวกเขา

$ for i in $(echo $str0 | grep -oP "\d+");do a=$(echo "$i" | wc -c); \
    echo "$a $i"; done | sort -n | tail -1 | cut -d" " -f2

ผล:

$ echo $str0
0000000000001a2test

$ for i in $(echo $str0 | grep -oP "\d+");do a=$(echo "$i" | wc -c); \
    echo "$a $i"; done | sort -n | tail -1 | cut -d" " -f2
0000000000001

${#var}คุณสามารถย่อบิตนี้โดยการใช้ความสามารถในการทุบตีเพื่อกำหนดความยาวของตัวแปรที่ใช้

$ for i in $(echo $str0 | grep -oP "\d+");do echo "${#i} $i"; done | \
    sort -n | tail -1 | cut -d" " -f2
0000000000001

ใช้ `grep -P

ฉันเลือกที่จะใช้grep -P ...ข้างต้นเพราะผมเป็นนักพัฒนา Perl เช่นไวยากรณ์ชั้นบอกว่าตัวเลขทุกคนชอบดังนั้น: \d+แทนหรือ[[:digit:]]\+ [0-9]\+แต่สำหรับปัญหานี้โดยเฉพาะมันไม่จำเป็นจริงๆ คุณสามารถเปลี่ยนได้อย่างง่ายดายจากที่grepฉันเคยใช้:

$ .... grep -o "[0-9]\+" ....

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

$ for i in $(echo $str0 | grep -o "[0-9]\+");do echo "${#i} $i"; done | \
    sort -n | tail -1 | cut -d" " -f2
0000000000001

2
ใช้${#i}เพื่อให้ได้ความยาวสายสามารถช่วยให้คุณประหยัดโทรwcถ้าคุณต้องการที่จะไปทุบตีเฉพาะ
เกล็น Jackman

@glennjackman - ขอบคุณที่เพิ่มการปรับปรุงของคุณใน A 8-)
slm

GNU grep 2.16 (อย่างน้อย) บอกว่า -P เป็น "การทดลองขั้นสูง" คุณสามารถใช้grep -o "[0-9]\+"แทนgrep -oP "\d+"
David Conrad

1
@DavidConrad - เพิ่มรายละเอียดเหล่านี้ไปยัง A ด้วยขอบคุณ!
slm


7

การใช้ python กับสตริงที่ส่งผ่าน commandline และสมมติว่าคุณต้องการลำดับแรกของความยาวสูงสุด:

import sys

longest = current = ""
for x in sys.argv[1]:
    if current and not x.isdigit():
        if len(current) > len(longest):
            longest = current
        current = ""
    else:
        current += x 
print(longest)

2
หรือ terselypython -c "import re,sys; print max(re.split(r'\D+', sys.argv[1]), key=len)"
iruvar

7

นี่เป็นอีกวิธี Perl ที่สามารถจัดการกับทศนิยมเช่นเดียวกับจำนวนเต็ม:

echo "0.212334123434test233" | 
 perl -lne 'while(/([\d.]+)/g){$max=$1 if length($1) > length($max)} print $max'

โปรดทราบว่าไม่มีคำตอบใด ๆ ที่โพสต์จนถึงขณะนี้จะจัดการกับทศนิยมและเนื่องจากคุณระบุว่าคุณต้องการหมายเลขที่ยาวที่สุดและไม่ใช่ตัวเลขที่ใหญ่ที่สุดฉันถือว่าคุณต้องการทศนิยม

คำอธิบาย

  • perl -lne: -nหมายถึง "อ่านบรรทัดอินพุตโดยบรรทัดและรันสคริปต์ที่กำหนดโดย-eบน" การ-lเพิ่มบรรทัดใหม่ให้กับการprintโทรแต่ละครั้ง(และสิ่งอื่น ๆ ที่ไม่เกี่ยวข้องที่นี่)
  • while(/([\d.]+)/g): ย้ำผ่านตัวเลขทั้งหมด ( \dหมาย[0-9]ดังนั้น[\d.]จะตรงกับตัวเลขและ.ถ้าคุณยังต้องการที่จะหาตัวเลขที่ติดลบเพิ่ม. -วงเล็บจับสตริงจับคู่เป็น. $1ซึ่งจะใช้ในขั้นตอนต่อไป
  • $max=$1 if length($1) > length($max): ถ้าความยาวของการแข่งขันในปัจจุบันที่มีค่ามากกว่าที่ยาวที่สุดเพื่อให้ห่างไกล ( $max) $maxบันทึกการแข่งขันเป็น
  • print $max: พิมพ์สตริงตัวเลขที่ยาวที่สุดที่พบ นี้จะถูกดำเนินการหลังจากที่ในขณะที่วงเสร็จสิ้นดังนั้นหลังจากพบตัวเลขทั้งหมด

1
+1 regex ของคุณค่อนข้างกว้างเกินไป มันจะจับคู่ที่อยู่ IP เช่น ฉันเสนอสิ่งที่ชอบ\D(\d+(?:\.\d+)?)\Dแทน
โจเซฟอาร์

ควรทำงานโดยไม่มี\Dสมอ ...
โจเซฟอาร์

@JosephR อืมจริงฉันไม่ได้พิจารณาอย่างต่อเนื่อง.เหมือนในที่อยู่ IP
terdon

6

ป.ร. ให้ไว้

str="212334123434test233"

จากนั้นในทุบตี

max=""
while read num; do 
  (( ${#num} > ${#max} )) && max=$num
done < <(grep -Eo '[0-9]+' <<< "$str")
echo $max
212334123434

วิธีทุบตีที่บริสุทธิ์กว่าอาจใช้อาเรย์ที่สร้างขึ้นโดยแทนที่อักขระที่ไม่ใช่ตัวเลขในสตริงด้วยช่องว่างแทนที่ grep

max=""
declare -a nums="${str//[^[:digit:]]/ }"
for num in ${nums[@]}; do 
  (( ${#num} > ${#max} )) && max=$num
done
echo $max

4

การสร้างคำตอบจาก @mikeserv นี่เป็นอีกทางเลือกหนึ่ง มันแยกตัวเลข (ตามวิธีของ mikeserv) จากนั้นเรียงลำดับตามตัวเลขและใช้ตัวเลขสุดท้าย ยกเว้นศูนย์นำหน้านี้จะทำให้คุณมีจำนวนมากที่สุด (ไม่คำนึงถึงการลงนาม):

echo 1111askdlfm2234 |  printf %s\\n $(tr -sc 0-9 \ ) | sort -n | tail -1

อันนี้ใช้งานได้จริง - ฉันไม่ได้ ฉันมีเครื่องหมาย 'ผิด'! ฉันจะลบมัน คุณสามารถใช้เปลือกเช่น -set -- $(echo $str | tr ... ) ; b=${#1} ; for d ; do [ ${#d} -gt $b ] && b=${#d} n=$d ; done ; echo $n
mikeserv

1
ฉันลบโพสต์ที่น่ากลัวของฉันและคุณจัดการเบา ๆ พอกับฉัน เนื่องจากคุณใช้trอยู่แล้วฉันจะไม่เสียใจถ้าคุณรวมสิ่งต่างๆข้างต้น อาจ sortจะเร็วขึ้น $(subshell)แต่แล้วอีกครั้งก็รอให้กระแสจบเช่นเดียวกับ ฉันไม่รู้ ไม่ว่าในกรณีใดคำตอบของคุณก็เป็นคำตอบที่ยอดเยี่ยมอยู่แล้ว แต่ถ้าคุณรู้สึกว่าการเพิ่มในห่วงของเชลล์ด้านบนรู้สึกฟรีนั่นคือทั้งหมดที่ฉันพูด และโดยวิธี - เป็นไปได้ที่คุณสามารถทำได้โดยไม่ต้องsortมีการจัดการที่สร้างสรรค์เล็กน้อยwc -Lและteeในกระแส ... ฉันทำกับคำถามนี้ - ฉันอาย
mikeserv

หนึ่งสิ่งสุดท้ายแม้ว่า - คุณเช่นกันอาจจะดึงtrออกมาจาก subshell printfและจะกำจัด '0-9' '\n'เพียงแค่ทำ
mikeserv

@mikeserv - สิ่งที่ดีเกี่ยวกับเว็บไซต์นี้คือเราเรียนรู้จากกันและกัน ขอบคุณสำหรับความช่วยเหลือของคุณ; โดยไม่มีคำตอบของคุณฉันจะไม่ได้มีการเริ่มต้นของตัวเอง ...
อริส

2

bash และ GNU เรียงลำดับ

IFS=$'\0' read -r l _ < <(tr -cs '[:digit:]' '[\0*]' <<<'11abcde1234556ghijk22'| sort -znr)
echo $l
1234556

2

ใช้อักขระที่ไม่ใช่ตัวเลขเพื่อแยกสตริงและค้นหาลำดับที่ยาวที่สุดหรือค่าตัวเลขที่ใหญ่ที่สุด (สำหรับหมายเลขที่มีความยาวเท่ากัน) ด้วยตัวดำเนินการที่ประกอบไปด้วย

$ echo "212334123434test233" | awk -F'[^0-9]+' '{for(i=1;i<=NF;i++){m=length($i)>=length(m)||$i>m?$i:m}};END{print m}'
212334123434

คุณยังสามารถตั้งค่าตัวคั่นเร็กคอร์ด awk ( RS) เป็นสตริงอักขระที่ไม่ใช่ตัวเลขได้:

$ echo "212334123434test233" \
    | awk -v RS='[^0-9]+' '
        length(longest) < length($0) {longest = $0};
        END{print longest}'
212334123434

2
ทำไมไม่เพียงแค่ตั้งค่าRS = '[^0-9]+'และใช้การวนซ้ำที่แท้จริงของ Awk echo "212334123434test233" | awk -v RS='[^0-9]+' 'length(longest) < length($0) {longest = $0};END{print longest}' 212334123434

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