匹配字符串中精确的数字位数

匹配字符串中精确的数字位数

给定一个字符串,如何找出它恰好包含 7 个连续数字?

例如15050821505082_CSE_322但不是1505082115050821_CSE_322

我试过了

grep -Eq [0-9]{7} <<< "1505082" 

返回0但是

grep -Eq [0-9]{7} <<< "15050821"` 

也归来0

我做错了什么?

答案1

是的,在(请引用正则表达式,否则它将被解释为 shell glob):

grep -Eq '[0-9]{7}' <<< "1505082"

grep 匹配 7 位数字。您可以通过将 q 替换为 an 来查看匹配的内容o

$ grep -Eo '[0-9]{7}' <<< "1505082"; echo "$?"
1505082
0

是的,它也会匹配这个:

$ grep -Eq '[0-9]{7}' <<< "150508299999"; echo "$?"
1505082
0

它消除了所有的九。
问题是您正在进行非锚定匹配,它将匹配 7 位数字 (或者更多) 数字。

你可以和:

$ grep -Eq '^[0-9]{7}$' <<< "15050829999"; echo "$?"
1

匹配 7 位数字任何地方并且后面或前面是非数字,您需要一个完全不同的锚点:

$ grep -oP '(?<=^|[^0-9])[0-9]{7}(?=[^0-9]|$)' <<< "1505082"; echo $?
1505082
0

$ grep -oP '(?<=^|[^0-9])[0-9]{7}(?=[^0-9]|$)' <<< "1505082_CSE_322"; echo $?
1505082
0

$ grep -oP '(?<=^|[^0-9])[0-9]{7}(?=[^0-9]|$)' <<< "1505082999_CSE_322"; echo $?
0

这些是前瞻匹配,一个是回顾:

(?<=^|[^0-9])

匹配字符串 ( ^) 的开头或非数字。另一个是前瞻:

(?=[^0-9]|$)

匹配非数字或字符串结尾。


使用更简单的正则表达式的唯一其他替代方法Extended是提取任意7(或更多)数字,然后确认它恰好是 7 位数字:

$ echo "150508299_CSE_322" | 
          grep -oE '[0-9]{7,}' | 
                  grep -qE '^[0-9]{7}$'; echo "$?"
1

答案2

当事情变得复杂时grep,您始终可以使用egreplinux/unix 系统中可用的编程语言来帮助您进行匹配/正则表达式。

如果您的系统有 perl 或 ruby​​,您可以一行完成:

echo 1234567| ruby -lne 'print if /^\d{7}$/'

echo 1234567| perl -lne 'print if /^\d{7}$/'

或者

cat file.txt | ruby -lne 'print if /^\d{7}$/'

答案3

为什么不使用 Bash 的二元运算符=~

$ [[ 1505082 =~ [0-9]{7} ]] && echo matched
matched

详情请参阅:http://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Conditional-Constructs

相关内容