【发布时间】:2012-05-14 08:38:14
【问题描述】:
我得到一个如下所示的字符串:
“abcderwer 123123 10,200 asdfasdf iopjjop”
现在我想提取数字,遵循 xx,xxx 方案,其中 x 是 0-9 之间的数字。例如。 10,200。必须是五位数字,并且必须包含“,”。
我该怎么做?
谢谢
【问题讨论】:
我得到一个如下所示的字符串:
“abcderwer 123123 10,200 asdfasdf iopjjop”
现在我想提取数字,遵循 xx,xxx 方案,其中 x 是 0-9 之间的数字。例如。 10,200。必须是五位数字,并且必须包含“,”。
我该怎么做?
谢谢
【问题讨论】:
你可以使用grep:
$ echo "abcderwer 123123 10,200 asdfasdf iopjjop" | egrep -o '[0-9]{2},[0-9]{3}'
10,200
【讨论】:
在纯 Bash 中:
pattern='([[:digit:]]{2},[[:digit:]]{3})'
[[ $string =~ $pattern ]]
echo "${BASH_REMATCH[1]}"
【讨论】:
简单的模式匹配(glob 模式)内置在 shell 中。假设您在$* 中有字符串(也就是说,它们是脚本的命令行参数,或者您在其他方式获得的字符串上使用了set),试试这个:
for token; do
case $token in
[0-9][0-9],[0-9][0-9][0-9] ) echo "$token" ;;
esac
done
【讨论】:
$@。有区别。
$*和$@肯定是有区别的;但我特别选择用原始 Bourne 名称来调用包含 argv 数组的变量,因为这是许多初学者级别的博览会使用的名称;在这种情况下,当您希望将值拆分为空格分隔的标记时,这就是脚本将使用的。我同意,如果您必须直接在脚本中引用位置参数,"$@" 几乎总是您想要的。
set -- 'abc def' ghi、for arg in "$@"; do echo "$arg"; done 是正确的。这些很少做正确的事情:$* 或 "$*"(很少 = 仅当您想要扁平化参数时)。继续重复初学者级别的错误说明是没有意义的。
for token; do 在这里做正确的事,不管你是怎么把东西放在那里的;有什么好争论的?
查看模式匹配和正则表达式。
链接:
如上所述,使用模式匹配的一种方法是使用 grep。 其他用途:echo 支持模式(globbing),find 支持正则表达式。
【讨论】:
echo 不适用,find 不适用于该问题。
一个稍微不典型的解决方案:
< input tr -cd [0-9,\ ] | tr \ '\012' | grep '^..,...$'
(第一个 tr 删除除逗号、空格和数字之外的所有内容。 第二个 tr 用换行符替换空格,将每个“数字”放在单独的 行,并且 grep 会丢弃除符合您的条件的所有内容。)
【讨论】:
以下使用输入数据字符串的示例应该可以解决使用 sed 的问题。
$ echo abcderwer 123123 10,200 asdfasdf iopjjop | sed -ne 's/^.*\([0-9,]\{6\}\).*$/\1/p'
10,200
【讨论】: