我需要提取(或计算)具有两个或更多点的行(在文件中)。这些行不应以点开头(如果它们是结尾与一个点),并且不能有两个点连续(即,点都用非点字符分隔)。
输出示例:
a.b.
a.b.com
a.b.c.
a.b.c.com
但不是:
a.com
a..b
a.b.c..d
我执行了这个命令:
grep -P '^[^.]+\.([^.]+\.)+[.]+' file.txt | wc -l
但没有找到任何匹配的行。我该怎么做?
答案1
\.
和[.]
是等价的——它们都匹配一个文字点,而不是任何其他字符。就风格而言,选择一种并持续使用它。- 你的问题是你的正则表达式(即模式)
([^.]+\.)+
后面跟着[.]+
.这实际上(某种程度上)相当于[^.]+\.
后跟[.]
,结果是您的 grep 正在寻找包含 的行 ,即连续两个点。如果你检查,你会发现你的命令匹配。text.text..
a.b..
- 好的,我相信修复相当简单:
grep -P '^[^.]+\.([^.]+\.)+[^.]*$'
即,将 更改[.]
为[^.]
(也许这就是您最初的意思?),将以下内容更改为+
,*
并添加$
.在一定数量的组之后,要求/允许除点之外的任何数量(零个或更多)字符,直到行尾。text.
- 一个更简单的方法(更容易理解)是
grep -P '^[^.]+\..*\.'文件.txt | grep -v '\.\.'
第一个grep
查找以非点字符开头且至少包含两个点的行。第二个grep
删除具有两个连续点的行。 - 与其做
grep … | wc -l
,不如做grep -c …
。
答案2
使用awk
:
$ cat file
.com
.c.c.c.c
a.b.
a.b.com
a.b.c.
a.b.c.com
a.com
a..b
a.b.c..d
$ awk -F . 'NF > 2 && !/^\./ && !/\.\./' file
a.b.
a.b.com
a.b.c.
a.b.c.com
这里的程序awk
使用点作为字段分隔符。具有两个或多个点的线与具有两个以上场的线相同。这就是NF > 2
测试所测试的。第一个正则表达式丢弃以点开头的行,第二个正则表达式丢弃连续包含两个或更多点的行。打印其余行。
同样的事情grep
:
grep '\..*\.' file | grep -v -e '^\.' -e '\.\.'
第一个表达式提取包含至少两个点的行,另外两个表达式删除以点开头或包含两个连续点的行。
或者与sed
,
sed -n '/^\./d; /\.\./d; /\..*\./p' file
答案3
您可以通过环视来做到这一点,如下所示:
$ grep -Pc '^(?!\.)(?!.*\.\..*)(?=.*\..*\.)' file.txt
读作:
- 我站在队伍的开头并向右看
^
- 我看到该行不是以文字点开头
(?!\.)
- 再往前看,我没有看到两个连续的文字点
(?!.*\.\..*)
- 但我确实看到了两个点,但由于在我之前的前瞻中排除了连续的点,这意味着这两个点必须由至少一个非点字符分隔
(?=.*\..*\.)
- 量子电动力学