如何打印字符串中最长的数字?

Glu*_*ate 11 sed awk text-processing

我正在寻找一种方法来打印字符串中最长的数字。

例如:如果我有字符串

212334123434test233
Run Code Online (Sandbox Code Playgroud)

我怎样才能打印

212334123434
Run Code Online (Sandbox Code Playgroud)

?

注意:我正在寻找最长的连续数字序列,而不是数字更高的值。


编辑:谢谢大家的回答。对这个问题的回答是相当压倒性的。我将@HaukeLaging 的帖子标记为已接受的答案,因为它非常适合我的具体情况,但我想指出所有答案都同样有效。有几种不同的选择来解决问题总是很好。

slm*_*slm 13

我相信你可以做到这一点只是grepsorttail也。下面是一些示例字符串。

$ echo <str> | grep -oP "\d+" | sort -n | tail -1
Run Code Online (Sandbox Code Playgroud)

<str>我们的字符串在哪里?

例子

$ set -o posix; set | grep "str[0-9]"
str0=212334123434test233
str1=212334123434test233abc44
str2=233test212334123434
str3=a212334123434test233abc44
str4=a91234b212334123434abc
Run Code Online (Sandbox Code Playgroud)

现在,如果我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
Run Code Online (Sandbox Code Playgroud)

这种方法的工作原理是选择所有数字序列的子串。然后我们按数字对这个输出进行排序sort -n,然后使用 获取列表中的最后一个值tail -1。这将是最长的子串。

您可以通过tail -1关闭并重新运行以下示例之一来了解它是如何工作的:

$ echo $str4 | grep -oP "\d+" | sort -n
91234
212334123434
Run Code Online (Sandbox Code Playgroud)

以零开头的字符串

上述方法适用于我能想到的每一种情况,除了一种情况。@terdon 在聊天中提到了这种情况,它挫败了上述方法。

  • 0000000000001
  • 2

所以要解决这个问题,你需要稍微改变策略。仍然可以利用上述方法的内核,但是我们也需要将字符数注入到结果中。这使 sort 能够按字符串中的字符数及其值对结果进行排序。

$ 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
Run Code Online (Sandbox Code Playgroud)

结果:

$ 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
Run Code Online (Sandbox Code Playgroud)

您可以通过利用 Bash 使用${#var}.

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

使用`grep -P

我选择使用grep -P ...上面的,因为我,作为一个 Perl 开发人员,喜欢这样说所有数字的类语法:\d+, 而不是[[:digit:]]\+or [0-9]\+。但是对于这个特定的问题,它并不是真正需要的。你可以grep像这样轻松地换掉我用过的:

$ .... grep -o "[0-9]\+" ....
Run Code Online (Sandbox Code Playgroud)

例如:

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

  • 使用 `${#i}` 来获取字符串长度可以节省你调用 `wc`,如果你想使用 bash 特定的 (2认同)

cuo*_*glm 8

解决方案perl

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

参考

  • 喜欢漂亮的施瓦兹变换! (2认同)

Hau*_*ing 7

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

212334123434
Run Code Online (Sandbox Code Playgroud)


Ant*_*hon 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)
Run Code Online (Sandbox Code Playgroud)

  • 或简洁的`python -c "import re,sys; print max(re.split(r'\D+', sys.argv[1]), key=len)"` (2认同)

ter*_*don 7

这是另一种可以处理小数和整数的 Perl 方法:

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

请注意,到目前为止发布的所有答案都不会涉及小数,并且由于您指定要最长的而不是数字最大的数字,因此我假设您实际上需要小数。

解释

  • 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 循环完成执行,因此在找到所有数字之后。


ste*_*ver 6

给定的

str="212334123434test233"
Run Code Online (Sandbox Code Playgroud)

然后在 bash

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

使用通过用空格替换字符串中的非数字字符来代替 grep 构造的数组的可能更纯的 bash 解决方案

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