문자열에서 가장 긴 숫자를 어떻게 인쇄합니까?


11

문자열에서 가장 긴 숫자를 인쇄하는 방법을 찾고 있습니다.

예 : 문자열이 있으면

212334123434test233

어떻게 인쇄 할 수 있습니까

212334123434

?

참고 : 나는 숫자가 더 높은 값이 아닌 가장 긴 연속적인 숫자 시퀀스를 찾고 있습니다.


편집 : 답변 주셔서 감사합니다. 이 질문에 대한 답변은 상당히 압도적입니다. @HaukeLaging의 게시물이 특정 사례에 매우 적합하기 때문에 허용되는 답변으로 표시했지만 모든 답변이 똑같이 유효하다는 것을 지적하고 싶습니다. 문제를 해결하기 위해 몇 가지 다른 옵션을 갖는 것이 항상 좋습니다.


동일하게 긴 연속 시퀀스가 ​​여러 개있을 때 방법이 어떻게 하시겠습니까? 첫 번째를 가지고? 마지막? 무작위?
Anthon

@Anthon Huh, 나는 그런 생각을하지 않았다. 운 좋게도 그것은 특정한 경우에는 문제가되지 않습니다. 옵션 중 하나라도 괜찮을 것 같습니다.
Glutanimate

3
수락 한 답변 (및 지금까지 하나를 제외한 다른 모든 답변 )은 소수를 처리하지 않습니다. 그것이 당신에게 문제가되는지 모르겠습니다.
terdon

@ terdon : 실제 숫자가 아닌 ID를 다루기 때문에 특정 경우에는 문제가되지 않지만 그럼에도 불구하고 귀하의 답변에 감사드립니다! 다른 사람이 앞으로 매우 유용 할 것이라고 확신합니다.
Glutanimate

솔루션에서 음수를 처리 할 수 ​​있도록 하시겠습니까? 그리고 그렇다면-빼기 기호는 길이를 계산합니까?
Floris

답변:


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

212334123434

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

0으로 시작하는 문자열

위의 접근 방식은 하나를 제외하고 생각할 수있는 모든 상황에 적용됩니다. @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 ...: 모든 숫자가 너무 좋아하는 말의 클래스 구문처럼 펄 개발자가되고, 내가 있기 때문에 위의 \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 당신은 bash는 특정 이동하려는 경우,
글렌 잭맨

@glennjackman-A 8-)에 개선 사항을 추가했습니다.
slm

GNU grep 2.16은 (적어도) -P는 "고성능"이라고 말합니다. grep -o "[0-9]\+"대신 사용할 수 있습니다grep -oP "\d+"
David Conrad

1
@DavidConrad-이러한 세부 사항을 A에 추가했습니다. 감사합니다!
slm

8

의 해결책 perl:

echo 212334123434test233abc44 |
perl -nle 'print ((
    map { $_->[0] }
    sort{ $a->[1] <=> $b->[1] }
    map { [$_,length] }
    split /\D+/, $_)[-1]
    )'
212334123434

참고 문헌


2
멋진 Schwartzian Transform을 좋아하십시오!
glenn jackman

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

다음은 정수뿐만 아니라 소수를 처리 할 수있는 또 다른 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: 발견 된 가장 긴 숫자 문자열을 인쇄합니다. while 루프가 완료된 후에 실행 되므로 모든 숫자를 찾은 후에 실행 됩니다.

1
+1 정규 표현식이 너무 일반적입니다. 예를 들어 IP 주소와 일치합니다. \D(\d+(?:\.\d+)?)\D대신에 비슷한 것을 제안 합니다.
Joseph R.

\D앵커 없이도 작동해야 합니다 ...
Joseph R.

@JosephR. 흠, 사실, .IP 주소처럼 연속적인 것으로 간주되지 않았습니다 .
terdon

6

주어진

str="212334123434test233"

bash에서

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의 방법에 따라) 숫자를 추출한 다음 숫자 순서로 정렬하고 마지막 숫자를 취합니다. 선행 0을 제외하면 가장 큰 숫자를 제공합니다 (기호를 고려하지 않음).

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

마지막으로 한 가지- tr서브 쉘을 꺼내서 제거 할 수도 있습니다 printf. 그냥하세요 '0-9' '\n'.
mikeserv

@ mikeserv-이 사이트에 대한 좋은 점은 우리가 서로에게서 배우는 것입니다. 당신의 도움을 주셔서 감사합니다; 당신의 대답 없이는 심지어 내 자신도 시작하지 않았을 것입니다 ...
Floris

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.