मैं एक स्ट्रिंग में सबसे लंबी संख्या कैसे प्रिंट कर सकता हूं?


11

मैं एक स्ट्रिंग में सबसे लंबी संख्या को प्रिंट करने के लिए एक विधि की तलाश कर रहा हूं।

जैसे: अगर मेरे पास तार है

212334123434test233

मैं कैसे प्रिंट कर सकता हूं

212334123434

?

नोट: मैं संख्याओं के सबसे लंबे निरंतर अनुक्रम की तलाश कर रहा हूं, संख्यात्मक रूप से उच्च मूल्य के लिए नहीं।


संपादित करें: सभी के जवाब के लिए धन्यवाद। इस सवाल की प्रतिक्रिया काफी भारी रही है। मैंने @ HaukeLaging की पोस्ट को स्वीकृत उत्तर के रूप में चिह्नित किया क्योंकि यह मेरे विशिष्ट मामले को बहुत अच्छी तरह से अनुकूल करता है लेकिन मैं यह बताना चाहता हूं कि सभी उत्तर समान रूप से मान्य हैं। किसी समस्या को हल करने के लिए कई अलग-अलग विकल्प रखना हमेशा बहुत अच्छा होता है।


जब आप कई समान रूप से लंबे निरंतर क्रम होते हैं, तो आप क्या करना चाहते हैं? सबसे पहले करें? अंतिम? एक यादृच्छिक एक?
एंथन

@ एंथन हुह, मैंने ऐसा नहीं सोचा था। सौभाग्य से यह मेरे विशिष्ट मामले में एक मुद्दा नहीं है। मुझे लगता है कि कोई भी विकल्प ठीक होगा।
Glutanimate

3
ध्यान दें कि आपने जो उत्तर स्वीकार किया है (और अब तक एक को छोड़कर बाकी सभी ) दशमलव संख्या के साथ सौदा नहीं करेंगे। मुझे नहीं पता कि यह आपके लिए समस्या है।
terdon

@terdon: यह मेरे विशिष्ट मामले में कोई समस्या नहीं है क्योंकि मैं वास्तविक संख्याओं के बजाय IDs के साथ काम कर रहा हूं लेकिन फिर भी मैं आपके उत्तर के लिए धन्यवाद देना चाहूंगा! मुझे यकीन है कि भविष्य में कोई और इसे बहुत उपयोगी पाएगा।
Glutanimate

क्या आप नकारात्मक संख्याओं से निपटने में सक्षम होना चाहते हैं? और अगर ऐसा है - क्या माइनस साइन की लंबाई की ओर इशारा करता है?
फ्लोरिस

जवाबों:



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 ...ऊपर का उपयोग करने का विकल्प चुना है क्योंकि मैं एक पर्ल डेवलपर होने के नाते, सभी अंकों को इस तरह कहने के वर्ग वाक्य रचना की तरह है: या \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, यदि आप बैश-विशिष्ट जाना चाहते हैं
ग्लेन जैकमैन

@glennjackman - धन्यवाद मेरे एक 8-) करने के लिए अपने सुधार जोड़ा
SLM

GNU grep 2.16 (कम से कम) कहता है- "अत्यधिक प्रयोगात्मक" है। आप grep -o "[0-9]\+"इसके बजाय का उपयोग कर सकते हैंgrep -oP "\d+"
डेविड कॉनरैड

1
@DavidConrad - इन विवरणों को A के साथ जोड़ा, धन्यवाद!
स्लम


7

पायथन का उपयोग स्ट्रिंग के साथ कमांडलाइन पर किया गया और यह मानते हुए कि आप अधिकतम लंबाई का पहला क्रम चाहते हैं:

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
या इसके python -c "import re,sys; print max(re.split(r'\D+', sys.argv[1]), key=len)"
विपरीत

7

यहाँ एक और पर्ल दृष्टिकोण है जो दशमलव के साथ-साथ पूर्णांकों से भी निपट सकता है:

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 आपका रेगेक्स थोड़ा सामान्य है, हालाँकि। यह उदाहरण के लिए आईपी पते से मेल खाएगा। मैं \D(\d+(?:\.\d+)?)\Dइसके बजाय कुछ पसंद करता हूं ।
जोसेफ आर।

\Dएंकरों के बिना भी काम करना चाहिए ...
जोसेफ आर।

@JosephR। हम्म, सच है, मैं लगातार .आईपी ​​पतों की तरह नहीं माना था ।
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

यह वास्तव में काम करता है - मेरा नहीं था। मैं गलत पक्ष पर 'r' था! मैं इसे हटाने जा रहा हूं। तुम भी सिर्फ खोल का उपयोग कर सकते हैं जैसे -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धारा के साथ कर सकें ... मैं इस सवाल के साथ किया जाता हूं - मैं शर्मिंदा हूं।
अभ्रक

एक आखिरी बात हालांकि - आप trसब-सब्सक्राइब से बाहर खींच सकते हैं और छुटकारा पा सकते हैं printf। बस करो '0-9' '\n'
मोकेसर 18

@mikeserv - इस साइट के बारे में अच्छी बात यह है कि हम एक-दूसरे से सीखते हैं। आपकी सहायता के लिए धन्यवाद; आपके जवाब के बिना मैं अपने दम पर शुरू भी नहीं होता ...
फ्लोरिस

2

बैश और जीएनयू सॉर्ट

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

आप RSकिसी भी गैर-संख्यात्मक वर्ण स्ट्रिंग के लिए awk का रिकॉर्ड विभाजक ( ) सेट कर सकते हैं :

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

2
क्यों न सिर्फ सेट करें RS = '[^0-9]+'और अवाक के निहित लूप का उपयोग करें? echo "212334123434test233" | awk -v RS='[^0-9]+' 'length(longest) < length($0) {longest = $0};END{print longest}' 212334123434

@awk_FTW आपको उत्तर के रूप में भी नीचे रखना चाहिए। :) मुझे RSचर दिखाने के लिए धन्यवाद , मुझे मानना ​​होगा कि यह पहली बार है जब मैं इसे देख रहा हूं। awkमेरे पास हाहा करने की तुलना में आपके पास और अधिक सुझाव हैं !
hjk
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.