文字列で最も長い数値を出力するにはどうすればよいですか?


11

文字列で最も長い数値を出力する方法を探しています。

例:文字列がある場合

212334123434test233

どうやって印刷できますか

212334123434

注:数値的に大きな値ではなく、最も長い連続した数列を探しています。


編集:皆さん、答えてくれてありがとう。この質問への回答は非常に圧倒されています。@HaukeLagingの投稿は、私の特定のケースに非常に適しているため、承認済みの回答としてマークしましたが、すべての回答が等しく有効であることを指摘しておきます。問題を解決するためのいくつかの異なるオプションがあることは常に素晴らしいことです。


同じ長さの連続したシーケンスが複数ある場合、メソッドはどのように処理しますか?最初に?最後?ランダム?
Anthon 2014

@Anthon Huh、私はそのことを考えていませんでした。幸いなことに、それは私の特定のケースでは問題ではありません。いずれのオプションも問題ないと思います。
グルタニメート2014

3
あなたが受け入れた答え(そしてこれまでのところ1つを除いて他のすべての答え)は10進数を扱いません。それがあなたにとって問題であるかどうかはわかりません。
terdon

@terdon:私は実際の番号ではなくIDを扱っているので、私の特定のケースでは問題ではありませんが、それでも回答に感謝したいと思います!将来、他の誰かが非常に役立つと確信しています。
グルタニメート2014

負の数を処理できるソリューションを希望しますか?そして、もしそうなら-マイナス記号は長さに向かってカウントされますか?
Floris 14

回答:


7
echo 212334123434test233abc44 | 
awk '{gsub("[^0-9]+","\n"); print;}' | 
awk '{ if (length($0) > max) {max = length($0); maxline = $0} } 
  END { print maxline }'

212334123434

13

私はあなただけでこれを行うことができると信じてgrepsorttailにも。文字列の例をいくつか示します。

$ 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

ゼロで始まる文字列

上記のアプローチは、1つを除いて、考えられるすべての状況で機能します。@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

を使用して変数の長さを決定するBashの機能を利用して、これを少し凝縮することができます${#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}文字列の長さを取得するためにを使用すると、wcbash固有にしたい場合にを呼び出すのを節約できます
glenn jackman '29

@glennjackman-おかげで私のAに改善が追加されました8
slm

GNU grep 2.16は(少なくとも)-Pは「非常に実験的」だと言っています。grep -o "[0-9]\+"代わりに使用できますgrep -oP "\d+"
David Conrad

1
@DavidConrad-これらの詳細をAにも追加しました、ありがとう!
slm


7

コマンドラインで渡された文字列でpythonを使用し、最大長の最初のシーケンスが必要だと仮定します。

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)"
iruvar 2014

7

次に、整数だけでなく小数も処理できる別のPerlのアプローチを示します。

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

これまでに投稿された回答はいずれも小数を扱っていないことに注意してください。数値的に最大の数ではなく、最も長くしたいことを指定したので、実際に小数が必要だと思います。

説明

  • perl -lne-n「入力を1行ずつ読み取り、-eそれによって指定されたスクリプトを実行する」という意味です。-lそれぞれに改行を追加してprintコール(および他のものここでは関係ありません)。
  • while(/([\d.]+)/g):すべての数値を反復処理します(\d[0-9][\d.]と一致するため、数字とに一致します.。負の数も検索する場合は、を追加し-ます。括弧$1は、次の手順で使用される一致した文字列をキャプチャします。
  • $max=$1 if length($1) > length($max):現在の一致の長さがこれまでの最長($max)より大きい場合、一致をとして保存し$maxます。
  • print $max:見つかった数字の最も長い文字列を出力します。これは、whileループの終了に実行されるため、すべての数値が検出されたに実行されます。

1
+1ただし、正規表現は少し一般的すぎます。たとえば、IPアドレスと一致します。\D(\d+(?:\.\d+)?)\D代わりに私は何かを提案します。
ジョセフR.

\Dアンカーなしでも動作するはずです...
ジョセフR.

@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の代わりに空白で置き換えることによって構築された配列を使用した、より純粋なbashソリューション

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 -Lteeストリームで完全になしで行うことが可能です...私はこの質問で終わりました-私は恥ずかしいです。
mikeserv 2014

ただし、最後にもう1つtr、サブシェルから引き出して取り除くこともできprintfます。するだけ'0-9' '\n'
mikeserv 2014

@mikeserv-このサイトの良いところは、お互いから学ぶことです。ご協力いただきありがとうございます; あなたの答えがなければ、私は自分で始めたことすらありませんでした...
フローリス

2

bashとGNUソート

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

2

数値以外の文字を使用して文字列を分割し、3項演算子を使用して最長のシーケンスまたは最大長の数値(長さが等しい数値の場合)を見つけます。

$ 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 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.