我有一个文件,其中的行看起来类似如下
data
datalater
983290842
Data387428later
datafhj893724897290384later
4329804928later
我要做的是使用正则表达式来匹配任何以数据开头并以后结束的行,并在其间包含数字。这是我到目前为止所编造的内容:
^[D,d]ata[0-9]*later$
但输出包括所有数据行。我想我可以管道输出和grep -v datalater,但我觉得单个表达式应该可以解决问题。
答案 0 :(得分:3)
使用+
代替*
。
+
至少匹配前面的一个或多个。
*
匹配零或更多。
^[Dd]ata[0-9]+later$
在grep中你需要转义+
,我们可以使用\d
这是一个字符类并匹配单个数字。
^[Dd]ata\d\+later$
在您的示例文件中,您还有一行:
datafhj893724897290384later
由于数据和数字之间存在字母,因此目前无法匹配。我们可以通过添加[^0-9]*
以匹配数据之后的任何内容直到数字来解决此问题。
我们的最终命令是:
grep '^[Dd]ata[^0-9]*\d\+later$' filename
答案 1 :(得分:2)
您使用*限定符匹配零个或多个数字。尝试
^[Dd]ata\d+later$
代替。你也在字符串的开头找到逗号(例如“,ata1234later”)。而\ d是查找任何数字字符的快捷方式。所以我也改变了。
答案 2 :(得分:1)
你应该加一个“+”(意思是一个或几个)而不是“*”(这意味着零,一个或几个
答案 3 :(得分:0)
使用Cygwin,上述命令不起作用。我不得不修改上面给出的命令以获得所需的结果。
$ cat > file.txt <<EOL
> data
> datalater
> 983290842
> Data387428later
> datafhj893724897290384later
> 4329804928later
> EOL
我总是希望确保我的文件符合我的预期:
$ cat file.txt
data
datalater
983290842
Data387428later
datafhj893724897290384later
4329804928later
$
我需要使用-P
标志运行Perl样式的表达式。这意味着我无法使用[^0-9]+
,其必要性@Tom_Cammann恰当地指出。相反,我使用.*
匹配任何与模式的下一部分不匹配的字符序列。这是我的命令和输出。
$ grep -P '^[Dd]ata.*\d+later$' file.txt
Data387428later
datafhj893724897290384later
$
我希望我能更好地解释为何需要Perl表达式,但我只知道Cygwin的grep
的工作方式有点不同。
系统信息
$ uname -a
CYGWIN_NT-10.0 A-1052207 2.5.2(0.297/5/3) 2016-06-23 14:29 x86_64 Cygwin
我之前回答的结果
$ grep '^[Dd]ata[^0-9]*\d\+later$' file2.txt
$ grep '^[Dd]ata\d+later$' file2.txt
$ grep -P '^[Dd]ata[^0-9]*\d\+later$' file2.txt
$ grep -P '^[Dd]ata\d+later$' file2.txt
Data387428later
$
答案 4 :(得分:0)
“ +”语法仅适用于扩展的正则表达式,不适用于标准grep。
至少,这就是我在RHEL上的经验。
要使用Extended-regexp,请运行egrep或传递“ -E” /“-extended-regexp” 例子...
标准grep
echo abc123n1 | grep "abc[0-9]+n1"
<no output>
egrep
echo abc123n1 | egrep "abc[0-9]+n1"
abc123n1
grep -E
echo abc123n1 | grep -E "abc[0-9]+n1"
abc123n1
HTH