如何从字符串中提取数字?
Posted
技术标签:
【中文标题】如何从字符串中提取数字?【英文标题】:How to extract numbers from a string? 【发布时间】:2013-07-26 20:37:59 【问题描述】:我有一个包含路径的字符串
string="toto.titi.12.tata.2.abc.def"
我只想从这个字符串中提取数字。
提取第一个数字:
tmp="$string#toto.titi.*."
num1="$tmp%.tata*"
提取第二个数字:
tmp="$string#toto.titi.*.tata.*."
num2="$tmp%.abc.def"
所以要提取参数,我必须分两步完成。如何一步提取一个数字?
【问题讨论】:
这个问题已经有一段时间了。如果没有一个答案提供您正在寻找的内容,那么您能否更新您的问题以进一步阐明您的要求?echo $string | grep -o -E "[0-9]+"
我认为是最简洁和最容易理解的(大多数人都知道 grep)。来自:***.com/a/52947167/52074
【参考方案1】:
如果您准确地提供了您想要获得的输出,这将更容易回答。如果您的意思是只想从字符串中获取数字,并删除其他所有内容,您可以这样做:
d@AirBox:~$ string="toto.titi.12.tata.2.abc.def"
d@AirBox:~$ echo "$string//[a-z,.]/"
122
如果您澄清一点,我可能会提供更多帮助。
【讨论】:
我更新了我的问题。我想提取 12,然后提取 2。不要同时提取两个数字【参考方案2】:您可以使用tr
删除所有非数字字符,如下所示:
echo toto.titi.12.tata.2.abc.def | tr -d -c 0-9
【讨论】:
这个输出似乎将所有数字混合在一起,在您的示例中形成122
。他们怎么可能分开?
为了将其设置为变量使用- PARAM=`echo toto.titi.12.tata.2.abc.def | tr -d -c 0-9 `【参考方案3】:
使用正则表达式匹配:
string="toto.titi.12.tata.2.abc.def"
[[ $string =~ toto\.titi\.([0-9]+)\.tata\.([0-9]+)\. ]]
# BASH_REMATCH[0] would be "toto.titi.12.tata.2.", the entire match
# Successive elements of the array correspond to the parenthesized
# subexpressions, in left-to-right order. (If there are nested parentheses,
# they are numbered in depth-first order.)
first_number=$BASH_REMATCH[1]
second_number=$BASH_REMATCH[2]
【讨论】:
【参考方案4】:使用 awk:
arr=( $(echo $string | awk -F "." 'print $3, $5') )
num1=$arr[0]
num2=$arr[1]
【讨论】:
【参考方案5】:你也可以使用 sed:
echo "toto.titi.12.tata.2.abc.def" | sed 's/[0-9]*//g'
这里,sed 替换了
任何数字([0-9]
类)
重复任意次数 (*
)
什么都没有(第二个和第三个/
之间什么都没有),
和g
代表全局。
输出将是:
toto.titi..tata..abc.def
【讨论】:
我认为 OP 想要数字,而不是字符串作为输出。 如果您想要数字,请使用^
反转匹配:echo "toto.titi.12.tata.2.abc.def" | sed 's/[^0-9]*//g'
。【参考方案6】:
参数扩展似乎是当务之急。
$ string="toto.titi.12.tata.2.abc.def"
$ read num1 num2 <<<$string//[^0-9]/
$ echo "$num1 / $num2"
12 / 2
这当然取决于$string
的格式。但至少对于您提供的示例,它似乎有效。
这可能优于 anubhava 需要子外壳的 awk 解决方案。我也喜欢 chepner 的解决方案,但正则表达式比参数扩展“更重”(尽管显然更精确)。 (请注意,在上面的表达式中,[^0-9]
可能看起来像一个正则表达式原子,但实际上不是。)
您可以在 bash 手册页中阅读有关此表单或参数扩展的信息。请注意,$string//this/that
(以及 <<<
)是一种 bashism,与传统的 Bourne 或 posix shell 不兼容。
【讨论】:
取决于$string
的格式到底是什么意思?我想不出任何可以打破它的例子。
嘿,这是一个老问题。 :) 此时我唯一能想到的是,如果有额外的数字,比如aa12aa34aa56
,并且您只读取两个变量,则尾随数字将添加到最后一个变量中,以空格分隔。如果这是一个问题,那么更好的解决方案可能是将字符串读入数组:read -a nums <<<"$string//[^0-9]/ "
.【参考方案7】:
提取所有单独的数字并通过 -
每行管道打印一个数字字tr '\n' ' ' | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' | tr -s ' ' | sed 's/ /\n/g'
细分:
用空格替换所有换行符:tr '\n' ' '
用空格替换所有非数字:sed -e 's/[^0-9]/ /g'
删除前导空格:-e 's/^ *//g'
删除尾随空格:-e 's/ *$//g'
按顺序将空格压缩为 1 个空格:tr -s ' '
用换行符替换剩余的空格分隔符:sed 's/ /\n/g'
例子:
echo -e " this 20 is 2sen\nten324ce 2 sort of" | tr '\n' ' ' | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' | tr -s ' ' | sed 's/ /\n/g'
会打印出来
20
2
324
2
【讨论】:
【参考方案8】:您好,添加另一种使用“剪切”的方法,
echo $string | cut -d'.' -f3,5 | tr '.' ' '
这将为您提供以下输出: 12 2
【讨论】:
【参考方案9】:这是一个简短的:
string="toto.titi.12.tata.2.abc.def"
id=$(echo "$string" | grep -o -E '[0-9]+')
echo $id // => output: 12 2
数字之间有空格。 希望对你有帮助...
【讨论】:
【参考方案10】:修复换行问题(对于 mac 终端):
cat temp.txt | tr '\n' ' ' | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' | tr -s ' ' | sed $'s/ /\\\n/g'
【讨论】:
以上是关于如何从字符串中提取数字?的主要内容,如果未能解决你的问题,请参考以下文章