Estou procurando um método para imprimir o número mais longo em uma string.
Por exemplo: se eu tiver a string
212334123434test233
como posso imprimir
212334123434
?
Nota: estou procurando a sequência contínua mais longa de números, não o valor numericamente mais alto.
Edit: Obrigado pelas respostas, pessoal. A resposta a esta pergunta foi bastante esmagadora. Marquei a postagem de @ HaukeLaging como a resposta aceita, pois se adequava muito bem ao meu caso específico, mas gostaria de ressaltar que todas as respostas são igualmente válidas. É sempre bom ter várias opções diferentes para resolver um problema.
text-processing
sed
awk
Glutanimado
fonte
fonte
Respostas:
fonte
Eu acredito que você pode fazer isso com apenas
grep
,sort
etail
tão bem. Aqui estão alguns exemplos de strings.Onde
<str>
está a nossa string em questão.Exemplo
Agora, se eu executar estes através do meu
grep ...
comando, por sua vez.Essa abordagem funciona selecionando todas as substrings que são sequências de dígitos. Em seguida, classificamos essa saída numericamente,
sort -n
e, em seguida, obtemos o último valor da lista, usandotail -1
. Essa será a substring mais longa.Você pode ver como ele funciona
tail -1
desativando e executando novamente um dos exemplos:Sequências que começam com zeros
A abordagem acima funciona para todas as situações que pude conceber, exceto uma. O @terdon mencionou no chat esse cenário que frustra a abordagem acima.
Então, para lidar com isso, você precisará mudar um pouco as táticas. O núcleo da abordagem acima ainda pode ser alavancado, no entanto, precisamos injetar o número de caracteres nos resultados também. Isso permite classificar os resultados por número de caracteres nas strings e seus valores.
Resultados:
Você pode condensar um pouco isso usando a capacidade do Bash para determinar o comprimento de uma variável usando
${#var}
.Usando `grep -P
Eu optei por usar
grep -P ...
acima porque eu, como desenvolvedor Perl, gosto da sintaxe da classe de dizer todos os dígitos assim: em\d+
vez de[[:digit:]]\+
ou[0-9]\+
. Mas, para esse problema em particular, não é realmente necessário. Você poderia facilmente trocar ogrep
que eu usei assim:Por exemplo:
fonte
${#i}
para obter o comprimento da corda pode poupar chamarwc
, se você quiser ir específicas de festagrep -o "[0-9]\+"
vez degrep -oP "\d+"
Uma solução em
perl
:Referências
fonte
Usando python com a string passada na linha de comando e supondo que você queira a primeira sequência de tamanho máximo:
fonte
python -c "import re,sys; print max(re.split(r'\D+', sys.argv[1]), key=len)"
Aqui está outra abordagem Perl que pode lidar com decimais e números inteiros:
Observe que nenhuma das respostas postadas até agora tratará de decimais e, como você especifica que deseja o número mais longo e não o maior numericamente, presumo que você realmente precise de decimais.
Explicação
perl -lne
: Os-n
meios "leem a entrada linha por linha e executam o script fornecido por-e
ela". O-l
adiciona uma nova linha a cadaprint
chamada (e outras coisas não relevantes aqui).while(/([\d.]+)/g)
: itera através de todos os números (\d
significa[0-9]
, portanto[\d.]
, coincidirá com dígitos e.
. Se você também quiser encontrar números negativos, adicione-
. Os parênteses capturam a sequência correspondente como$1
é usada na próxima etapa.$max=$1 if length($1) > length($max)
: Se a duração da correspondência atual for maior que a mais longa até agora ($max
), salve a correspondência como$max
.print $max
: imprime a maior seqüência de números encontrada. Isso será executado depois que o loop while terminar, portanto, depois que todos os números forem encontrados.fonte
\D(\d+(?:\.\d+)?)\D
.\D
âncoras ....
como nos endereços IP.Dado
então no bash
Uma solução bash possivelmente mais pura usando uma matriz construída substituindo caracteres não dígitos na cadeia de caracteres por espaço em branco, no lugar do grep
fonte
Com base na resposta de @mikeserv, aqui está outra alternativa. Extrai os números (pelo método de mikeserv), depois os classifica em ordem numérica e pega o último. Com exceção de zeros à esquerda, você obterá o maior número (sem considerar o sinal):
fonte
set -- $(echo $str | tr ... ) ; b=${#1} ; for d ; do [ ${#d} -gt $b ] && b=${#d} n=$d ; done ; echo $n
tr
qualquer maneira, eu não guardaria rancor se você incorporasse o item acima. Provavelmentesort
é mais rápido, mas, novamente, aguarda o término do fluxo da mesma forma que o$(subshell)
. Eu não sei. De qualquer forma, a sua já é uma excelente resposta, mas se você quiser adicionar o loop de shell acima, fique à vontade é tudo o que estou dizendo. E, a propósito - é possível que você não tenhasort
como lidar com um pouco de criatividadewc -L
etee
fluxo - acabei com essa pergunta - estou envergonhado.tr
sair do subconjunto e se livrar deleprintf
. Apenas faça'0-9' '\n'
.classificação bash e GNU
fonte
Use caracteres não numéricos para dividir a sequência e encontre a sequência mais longa ou o maior valor numérico (para números de igual comprimento) com um operador ternário.
Você também pode definir o separador de registros do awk (
RS
) como qualquer sequência de caracteres não numéricos:fonte
RS = '[^0-9]+'
e usar o loop inerente do Awk?echo "212334123434test233" | awk -v RS='[^0-9]+' 'length(longest) < length($0) {longest = $0};END{print longest}' 212334123434
RS
variável, devo admitir que é a primeira vez que a vejo. Você tem mais dicas a oferecer doawk
que eu hahaha!