Bash:如何获取出现在变量内容中的第一个数字


8

如何获得第一个变量

我有一个变量:

STR="My horse weighs 3000 kg but the car weighs more"
STR="Maruska found 000011 mushrooms but only 001 was not with meat"
STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

我需要获取数字:

3000
11
20

Answers:


7

使用gawk,将记录分隔符设置RS为数字序列。RS可以通过检索与模式匹配的文本RT。添加0RT它迫使一些(从而丢弃前导零)。首次打印后退出

awk -v RS=[0-9]+ '{print RT+0;exit}' <<< "$STR"

或者这是一个bash解决方案

shopt -s extglob
read -r Z _ <<< "${STR//[^[:digit:] ]/}"
echo ${Z##+(0)}

真好 您想详细说明吗?
jasonwryan 2013年

我不明白 我在做什么错(awk版本)?gist.github.com/jamiejackson/d92750cc42442a527c6b94499a13bc79
Jamie Jackson

@JamieJackson,确保您正在运行GNU awk aka gawk
iruvar,

5

这是一种实现方法:

echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'

测试:

$ STR="My horse weighs 3000 kg but the car weighs more"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
3000

$ STR="Maruska found 000011 mushrooms but only 001 was not with meat"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
11

$ STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
20

最后的目的是什么sed?似乎在进入sed之前,我们已经有了想要的结果。
迈克尔

不,您必须为#2 000011删除前导零。但是您可以通过匹配来简化,[1-9][0-9]*从一开始就将其删除前导零: echo $STR | grep -o -E '[1-9][0-9]*'
CCH

2

如果您的实现grep不存在-o或不使用Bash,则可以执行以下操作:

printf "%.0f\n" $(printf "%s" "$string"|sed  's/^[^0-9]*//;s/[^0-9].*$//')

2
#!/bin/bash

string="My horse weighs 3000 kg but the car weighs more"

if [[ $string =~ ^([a-zA-Z\ ]*)([0-9]*)(.*)$ ]]
then
    echo ${BASH_REMATCH[1]}
fi  

1
下标应该是2而不是1。但是您实际上不需要那种复杂的正则表达式。如果字符串中还有其他字符,则无论如何都会失败。
暂停,直到另行通知。

2

我将您的字符串放入数组中,以便在本演示中可以轻松地对其进行迭代。

这使用了Bash的内置正则表达式匹配。

只需要一个非常简单的模式。建议使用变量保存模式,而不是直接将其合并到匹配测试中。这对于更复杂的模式至关重要。

str[0]="My horse weighs 3000 kg but the car weighs more"
str[1]="Maruska found 000011 mushrooms but only 001 was not with meat"
str[2]="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

patt='([[:digit:]]+)'

for s in "${str[@]}"; do [[ $s =~ $patt ]] && echo "[${BASH_REMATCH[1]}] - $s"; done

我包括方括号只是为了直观地显示数字。

输出:

[3000] - My horse weighs 3000 kg but the car weighs more
[000011] - Maruska found 000011 mushrooms but only 001 was not with meat
[0000020] - Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK

要获得没有前导零的数字,最简单的方法是强制以10为基数的转换。

echo "$(( 10#${BASH_REMATCH[1]} ))"

代之以,输出看起来像您所要求的:

3000
11
20

1

查找正则表达式和man grep

echo $STR | grep -o [0-9]*

并删除前导零,将其视为数字:

LIT=$(echo $STR | grep -o [0-9]*)
VAL=$(expr $LIT + 0)
echo $VAL

您的解决方案失败,变量包含两个数字或数字填充零。
cuonglm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.