22

我有字符串包含一个路径

string="toto.titi.12.tata.2.abc.def"

我只想从此字符串中提取数字。

提取第一个数字:

tmp="${string#toto.titi.*.}"
num1="${tmp%.tata*}"

要提取第二个数字:

tmp="${string#toto.titi.*.tata.*.}"
num2="${tmp%.abc.def}"

因此,要提取参数,我必须分两步完成。如何一步提取一个数字?

4

10 回答 10

19

您可以使用tr删除所有非数字字符,如下所示:

echo toto.titi.12.tata.2.abc.def | tr -d -c 0-9
于 2013-07-26T15:02:56.310 回答
12

要提取所有单独的数字并通过 - 每行管道打印一个数字字 -

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
于 2015-05-27T18:28:55.227 回答
8

这是一个简短的:

string="toto.titi.12.tata.2.abc.def"
id=$(echo "$string" | grep -o -E '[0-9]+')

echo $id // => output: 12 2

数字之间有空格。希望能帮助到你...

于 2018-10-23T10:49:13.873 回答
5

参数扩展似乎是当务之急。

$ string="toto.titi.12.tata.2.abc.def"
$ read num1 num2 <<<${string//[^0-9]/ }
$ echo "$num1 / $num2"
12 / 2

这当然取决于$string. 但至少对于您提供的示例,它似乎有效。

这可能优于需要 subshel​​l 的 anubhava 的 awk 解决方案。我也喜欢 chepner 的解决方案,但正则表达式比参数扩展“更重”(尽管显然更精确)。(请注意,在上面的表达式中,[^0-9]可能看起来像一个正则表达式原子,但它不是。)

您可以在 bash 手册页中阅读有关此表单或参数扩展的信息。请注意,${string//this/that}( 以及<<<) 是一种 bashism,并且与传统的 Bourne 或 posix shell 不兼容。

于 2015-03-10T15:38:14.663 回答
2

如果您准确地提供了您想要获得的输出,这将更容易回答。如果您的意思是您只想从字符串中获取数字,并删除其他所有内容,您可以这样做:

d@AirBox:~$ string="toto.titi.12.tata.2.abc.def"
d@AirBox:~$ echo "${string//[a-z,.]/}"
122

如果您澄清一点,我可能会提供更多帮助。

于 2013-07-26T15:00:45.913 回答
2

您还可以使用 sed:

echo "toto.titi.12.tata.2.abc.def" | sed 's/[0-9]*//g'

在这里, sed 替换

  • 任何数字(类[0-9]
  • 重复任意次数 ( *)
  • 什么都没有(第二个和第三个之间什么都没有/),
  • g代表全球。

输出将是:

toto.titi..tata..abc.def
于 2013-07-29T13:46:32.253 回答
1

使用正则表达式匹配:

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]}
于 2013-07-26T19:07:31.633 回答
1

使用 awk:

arr=( $(echo $string | awk -F "." '{print $3, $5}') )
num1=${arr[0]}
num2=${arr[1]}
于 2013-07-26T19:21:54.763 回答
1

嗨,添加另一种使用“剪切”的方法,

echo $string | cut -d'.' -f3,5 | tr '.' ' '

这将为您提供以下输出:12 2

于 2017-07-30T06:36:44.343 回答
0

修复换行问题(对于 mac 终端):

cat temp.txt | tr '\n' ' ' | sed -e 's/[^0-9]/ /g' -e 's/^ *//g' -e 's/ *$//g' | tr -s ' ' | sed $'s/ /\\\n/g'
于 2020-02-29T22:44:44.827 回答