给定一个字符串,如何找出它恰好包含 7 个连续数字?
例如1505082
或1505082_CSE_322
但不是15050821
或15050821_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
,您始终可以使用egrep
linux/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