我正在寻找一种打印字符串中最长数字的方法。
例如:如果我有字符串
212334123434test233
我怎样才能打印
212334123434
?
注意:我正在寻找最长的连续数字序列,而不是数字上更高的值。
编辑:谢谢大家的回答。对于这个问题的回答非常热烈。我将@HaukeLaging 的帖子标记为已接受的答案,因为它非常适合我的具体情况,但我想指出所有答案都同样有效。有几种不同的选择来解决问题总是很棒的。
答案1
我相信你也可以用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
因此,要解决这个问题,您需要稍微改变策略。仍然可以利用上述方法的核心,但是我们也需要将字符数注入到结果中。这使得 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
结果:
$ 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:]]\+
or [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
解决方案perl
:
echo 212334123434test233abc44 |
perl -nle 'print ((
map { $_->[0] }
sort{ $a->[1] <=> $b->[1] }
map { [$_,length] }
split /\D+/, $_)[-1]
)'
212334123434
参考
答案3
echo 212334123434test233abc44 |
awk '{gsub("[^0-9]+","\n"); print;}' |
awk '{ if (length($0) > max) {max = length($0); maxline = $0} }
END { print maxline }'
212334123434
答案4
这是另一种可以处理小数和整数的 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 循环结束,所以在找到所有数字之后。