Regex Bash:我如何提取所有“的计数”;";字符串中的数字?

Regex Bash:我如何提取所有“的计数”;";字符串中的数字?,regex,bash,Regex,Bash,我试图使用bash从字符串中提取n个数字的总数 例如,对于3位数字 I am trying to extract 3 digited numbers 333, 334, 335 from this string #should return 3 I have 243 pens for sale #should return 1 不幸的是,我无法将sed或grep与perl regexp一起使用 感谢您的建议 可以在bash中使用正则表达式 #/bin/bash cat假设OP只需要精确的3位数

我试图使用bash从字符串中提取n个数字的总数

例如,对于3位数字

I am trying to extract 3 digited numbers 333, 334, 335 from this string #should return 3
I have 243 pens for sale #should return 1
不幸的是,我无法将
sed
grep
perl regexp
一起使用


感谢您的建议

可以在bash中使用正则表达式

#/bin/bash

cat假设OP只需要精确的3位数字,而不想将较长的数字细分为3位数字段,例如,字符串
12345
将返回零计数,而不是3计数(
123
/
234
/
345


一些样本数据:

$ cat numbers.dat
I am trying to extract 3 digited numbers 333, 334, 335 from this string #should return 3
I have 243 pens for sale #should return 1
123 xyz
def 456
def 789-345 abc                    # should match 7-8-9 and 3-4-5
tester876tester                    # should match 8-7-6
testing9999testing                 # should not match 9-9-9-9

$ str=$(cat numbers.dat)           # load data into a variable
两次通过的
grep
解决方案:

注意:借用了Asisp的单词边界标志(
\b

查找具有非数字书尾的3位数图案(包括行首/行尾)

将计数存储在变量中:

$ counter=$(grep -Eo '(^|[^0-9]|\b)[0-9]{3}(\b|[^0-9]|$)' numbers.dat | grep -Eo '[0-9]{3}' | wc -l)
# or
$ counter=$(grep -Eo '(^|[^0-9]|\b)[0-9]{3}(\b|[^0-9]|$)' <<< "${str}" | grep -Eo '[0-9]{3}' | wc -l)

$ echo "${counter}"

9
$counter=$(grep-Eo'(^[0-9]|\b)[0-9]{3}(\b[0-9]|$)'numbers.dat | grep-Eo'[0-9]{3}wc-l)
#或

$counter=$(grep-Eo'(^ |[^0-9]|\b)[0-9]{3}(\b |[^0-9]|$)”仅使用POSIX外壳语法:

!/usr/bin/env sh
#应该返回3
str1='我正试图从该字符串中提取3个数字333334335'
#应该返回1
str2='我有243支钢笔出售'
#应该返回2
str3='这是123456'
_OIFS=$IFS
IFS=$IFS',.:;!?-\u+=*.$§^&{}[].124;`@“()\\/'\'
对于“$str1”$str2“$str3”中的str
做
计数=0
对于$str中的单词
做
case$word in
[[:位:][[:位:][[:位:][[:位:]
计数=$((计数+1))
;;
以撒
完成
printf'字符串:\n%s\n->计数:%d\n\n'$str'$Count“
完成
IFS=$\u OIFS
输出:

字符串:
我试图从这个字符串中提取3个数字333334335
->计数:3
字符串:
我有243支钢笔出售
->计数:1
字符串:
这里是123456
->计数:2
通过这种方式,我们匹配单词边界中的3位数字,这些数字允许重复使用(例如,如果两个数字由一个边界字符分隔,如逗号或空格)

或者像这样:

echo "$str" | grep -o '\<[[:digit:]]\{3\}\>' | wc -l
echo“$str”| grep-o'\'| wc-l

您可以尝试使用以下链接编写并测试以下内容吗 在显示的示例中。由于OP在注释中表示数字之前/之间/之后不能有任何其他内容(除了
,我相信根据示例),因此遍历当前行的所有字段并使用正则表达式为其查找匹配项

awk '
{
  for(i=1;i<=NF;i++){
    if(match($i,/^[0-9]{3}[,]?$/)){
       count++
    }
  }
  print "Line " FNR " has " count " number of 3 digits."
  count=""
}
' Input_file


不,限制是因为我必须在一个不支持<代码> Perl ReXEP< <代码>的远程服务器上做这件事。关于<代码> A123,<代码> 456版< /代码>,代码> 123-466>代码>,你想考虑其中的任何一个结果吗?在它们之前/之后/之间。您将无法匹配由单个字符分隔的有界3位数字。
123 456
。是否想过使用Perl?您将至少需要一个前瞻功能。@thanasisp
\b[0-9][0-9][0-9]\b
a123b
中的123不匹配,这将计算至少包含3个数字的单词,而不是我解释OP所需要的正好3个数字的单词。@glennjackman谢谢。它现在已经修复了!这将匹配此字符串中的456吗
123 456
?它还必须匹配123。@Maxt8r是的,它将计算
123 456
为2组3位数字。您是否按非数字进行拆分?当您在
中说
word时,这是否考虑了4位或更多的数字,其中3位是子集,还是必须与word中的整个文本匹配?似乎应该有更好的实用程序来执行此操作。与此处的456不匹配
123 456
@Maxt8r:它显示“2”“对于
123456
。哦,很抱歉,我没有意识到bash regex无法进行全局匹配。是的,我应该意识到唯一的方法是每次传球都要重新制作/修剪线,直到没有更多的比赛。注意:追加
${BASH_REMATCH[3]}
似乎没有必要。此外,如果需要多个重叠,则会变得更加棘手。哇,想象一下一次要匹配数百万个这样的东西。每次制作一个新字符串的开销太大,这将非常耗时。所以,它可能是一个简洁的演示技巧,但它不是一种进行大量匹配的方法。@Maxt8r:你说得对,我已经删除了附加项。如果性能是一个问题,不要使用bash。非常正确。在过去的一个小时里,我刚刚自学了bash,只是为了了解您使用的字符串语法。非常隐晦,几乎是一个原始的perl。我还提供了稍微更直观的:
echo“$str”| grep-o'[0-9][0-9][0-9][0-9]”wc-l
它实际上会打印
0
,但我现在看到两端都需要
\b
。也许要完全回答“n”数字的问题,我们必须说:
echo“123”,“grep-o”\b[0-9]\{${N}\}\b“| wc-l
其中
N=3
对于本例
$ grep -Eo '(^|[^0-9]|\b)[0-9]{3}(\b|[^0-9]|$)' numbers.dat | grep -Eo '[0-9]{3}' | wc -l
# or
$ grep -Eo '(^|[^0-9]|\b)[0-9]{3}(\b|[^0-9]|$)' <<< "${str}" | grep -Eo '[0-9]{3}' | wc -l

9
$ counter=$(grep -Eo '(^|[^0-9]|\b)[0-9]{3}(\b|[^0-9]|$)' numbers.dat | grep -Eo '[0-9]{3}' | wc -l)
# or
$ counter=$(grep -Eo '(^|[^0-9]|\b)[0-9]{3}(\b|[^0-9]|$)' <<< "${str}" | grep -Eo '[0-9]{3}' | wc -l)

$ echo "${counter}"

9
echo "$str" | grep -o '\b[0-9]\{3\}\b' | wc -l
echo "$str" | grep -o '\<[[:digit:]]\{3\}\>' | wc -l
awk '
{
  for(i=1;i<=NF;i++){
    if(match($i,/^[0-9]{3}[,]?$/)){
       count++
    }
  }
  print "Line " FNR " has " count " number of 3 digits."
  count=""
}
' Input_file
Line 1 has 3 number of 3 digits.
Line 2 has 1 number of 3 digits.