我正在寻找一种打印字符串中最长数字的方法。
例如:如果我有字符串
212334123434test233
我该如何打印
212334123434
?
注意:我正在寻找最长的连续数字序列,而不是数字更高的值。
编辑:谢谢大家的回答。对这个问题的反应非常热烈。我将@HaukeLaging的帖子标记为可接受的答案,因为它非常适合我的具体情况,但我想指出,所有答案都同样有效。有几种不同的选择解决一个问题总是很高兴。
我正在寻找一种打印字符串中最长数字的方法。
例如:如果我有字符串
212334123434test233
我该如何打印
212334123434
?
注意:我正在寻找最长的连续数字序列,而不是数字更高的值。
编辑:谢谢大家的回答。对这个问题的反应非常热烈。我将@HaukeLaging的帖子标记为可接受的答案,因为它非常适合我的具体情况,但我想指出,所有答案都同样有效。有几种不同的选择解决一个问题总是很高兴。
Answers:
echo 212334123434test233abc44 |
awk '{gsub("[^0-9]+","\n"); print;}' |
awk '{ if (length($0) > max) {max = length($0); maxline = $0} }
END { print maxline }'
212334123434
我相信你可以做到这一点只是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在聊天中提到了这种情况,它挫败了上述方法。
因此,要解决此问题,您需要稍微改变策略。仍然可以利用上述方法的内核,但是我们也需要在结果中注入字符数。这使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 ...
上述代码,是因为我是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
${#i}
获取字符串长度可以节省调用费用wc
grep -o "[0-9]\+"
,而不是grep -oP "\d+"
解决方案perl
:
echo 212334123434test233abc44 |
perl -nle 'print ((
map { $_->[0] }
sort{ $a->[1] <=> $b->[1] }
map { [$_,length] }
split /\D+/, $_)[-1]
)'
212334123434
将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)
python -c "import re,sys; print max(re.split(r'\D+', sys.argv[1]), key=len)"
这是可以处理小数和整数的另一种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循环完成后执行,因此在找到所有数字之后。\D(\d+(?:\.\d+)?)\D
。
\D
锚的情况下工作...
.
像IP地址那样连续。
给定
str="212334123434test233"
然后猛扑
max=""
while read num; do
(( ${#num} > ${#max} )) && max=$num
done < <(grep -Eo '[0-9]+' <<< "$str")
echo $max
212334123434
可能是更纯正的bash解决方案,它使用通过将字符串中的非数字字符替换为空格而不是grep构造而成的数组
max=""
declare -a nums="${str//[^[:digit:]]/ }"
for num in ${nums[@]}; do
(( ${#num} > ${#max} )) && max=$num
done
echo $max
在@mikeserv的答案的基础上,这是另一种选择。它提取数字(按照mikeserv的方法),然后按数字顺序对其进行排序,并获取最后一个。除前导零外,这将为您提供最大的数字(不考虑符号):
echo 1111askdlfm2234 | printf %s\\n $(tr -sc 0-9 \ ) | sort -n | tail -1
set -- $(echo $str | tr ... ) ; b=${#1} ; for d ; do [ ${#d} -gt $b ] && b=${#d} n=$d ; done ; echo $n
tr
了,那么如果您结合了以上内容,我将不会怀恨在心。可能 sort
速度更快,但是话又说回来,它等待流结束与相同$(subshell)
。我不知道。无论如何,您的答案已经是一个不错的选择,但是如果您想在上述shell循环中添加代码,那就很随意了。顺便说一句-这是可能的,你可以不这样做sort
完全用一点创新的处理wc -L
和tee
在流......我这个问题,虽然做了-我很尴尬。
tr
退出子外壳并摆脱它printf
。做吧'0-9' '\n'
。
使用非数字字符分割字符串,并使用三元运算符查找最长的序列或最大的数值(对于等长数字)。
$ 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
RS = '[^0-9]+'
和使用Awk的固有循环?echo "212334123434test233" | awk -v RS='[^0-9]+' 'length(longest) < length($0) {longest = $0};END{print longest}' 212334123434
RS
变量,我必须承认这是我第一次看到它。您提供的提示要awk
多于我!