2014-02-09 52 views
2

我有问题了解我的正则表达式在bash shell中的确正在做什么。正则表达式匹配只有数字

我有字符串abcde 12345 67890testing。我想使用sed从这个字符串中提取12345

但是,使用sed -re 's/([0-9]+).*/\1/'对给定的字符串将给我abcde 12345。另外,使用sed -re 's/([\d]+).*/\1/'实际上只提取abcd

我错了,假设表达式[0-9][\d]只捕获数字?我不知道如何abcd被捕获,但字符串67890不是。另外,我想知道为什么在我的第一个查询中捕获空间?另外,sed -re 's/^.*([0-9]+).*/\1/'给我0。在这种情况下,我完全不明白正则表达式在做什么。我以为表达式^.*[0-9]+只会捕获一串唯一数字的第一个实例?不过,它只匹配最后一个0.总之,我想了解我对所有这些问题的看法。以及如何在正则表达式中使用[\ s]来解决问题,以隔离第一个数字串。

+0

问题是你的'sed'命令是这样的:“在每一行上,找到一些数字后跟任意数量的字符,一个用数字替换那个匹配。“它正在执行指定的内容,即用'12345'替换12345 67890testing'。相反,你想用什么都替换最初的匹配。不幸的是,据我所知,没有办法在'sed'表达式的前面放置一个非贪婪的'。*?',而内联Perl或Ruby可能是更好的选择。 – chrylis

回答

0

您可以使用:

sed 's/^\([0-9]*\).*$/\1/g' <<< "$s" 
12345 

否则修改您的sed:

sed 's/\([0-9]\+\).*/\1/g' <<< "$s" 
12345 

你一定要逃逸无扩展的正则表达式标志(-r OR -E)的sed + & (and)

-r这将是:

sed -r 's/([0-9]+).*/\1/g' <<< "$s" 
12345 

UPDATE:你并不真的需要这方面的任何外部工具,你可以使用正则表达式的能力,这样做在BASH本身:

[[ "$s*" =~ ^([0-9]+) ]] && echo "${BASH_REMATCH[1]}" 
12345 
+0

谢谢你的回复。然而,使用'sed -r'/([0-9] +)。*/\ 1/g'<<<“$ s”'会使我产生'abcd 12345' 我不确定它是如何抓住'abcd' – user3289476

+0

'sed -r's /([0-9] +)。*/\ 1/g'<<<“$ s”'给我'12345' – anubhava

+1

您能否解释一下使用背后的想法这是一个字符串?据我所知,这只是在Bash变量's'的内容上运行'sed'表达式,这似乎没有帮助。 – chrylis

3
sed -E 's/([0-9]+).*/\1/g' <<< "$s" 

上面的命令意味着:找到一个数字序列后面跟一个东西,并用数字替换它。所以它匹配12345 67890测试并且仅用来代替它。

最后的字符串将是abcd 12345

如果你只想得到12345,你应该使用grep。

egrep -o '[0-9]+ ' <<< "$s" 

或者使用sed,您可以使用:

sed -E 's/[a-zA-Z ]*([0-9]+).*/\1/g' <<< "$s" 

这将数字

+0

对于我的最后一次尝试,是使用贪婪的表达式'。*'进入字符串的其余部分,直到它只剩下'0'?似乎不可能使用贪婪的表达式去除前面的问题的abcde部分呢? – user3289476

+0

如果你使用。*([0-9] +)。*它只会匹配最后一个数字,因为+意味着1或更多,所以它会最小化。如果你确切地知道你可以使用的数字序列的长度,*([0-9] {5})。*和)之间必须有一个空格。 – drolando

0

之前下降的字母,因为别人已经具备SED,grep的解决方案,这里是awk的代码:

echo "abcde 12345 67890testing"|awk '{for (i=1;i<=NF;i++) if ($i~/^[0-9]+$/) print $i}'