Grep表达式过滤掉[alnum] [punct] [alnum]

时间:2016-08-24 05:04:55

标签: text command-line grep pattern-matching data-processing

您好我的第一篇文章是我认为简单的...

我无法找到类似问题/解决方案的示例。

我有数千个文本文件,其中包含数千行内容

<word><space><word><space><number>

示例:

    example for 1
    useful when 1
    for. However 1
    ,boy wonder 1
    ,hary-horse wondered 2

在上面的示例中,我想排除第3行,因为它包含内部标点符号

我正在尝试使用GNU grep 2.25,但没有运气

我最初的尝试是(但这不允许模式内部的“ - ”):

grep -v [:alnum:]*[:punct:]*[:alnum:]* filename 

所以试过这个

grep -v [:alnum:]*[:space:]*[!]*["]*[#]*[$]*[%]*[&]*[']*[(]*[)]*[*]*[+]*[,]*[.]*[/]*[:]*[;]*[<]*[=]*[>]*[?]*[@]*[[]*[\]*[]]*[^]*[_]*[`]*[{]*[|]*[}]*[~]*[.]*[:space:]*[:alnum:]* filename 

但是我需要考虑空格和 - 因为这些是字符串内部可接受的。

我一直在尝试使用:punct“set但是现在看到它包含 - 显然不会起作用

我目前在TSQL中有一个存储过程来处理这些,但是如果可能的话,我希望在加载之前进行预处理,因为例程每个文件需要几秒钟。

有人能够取得类似的成就吗?

2 个答案:

答案 0 :(得分:1)

你的正则表达式包含一长串有序的可选元素,但这意味着如果出现故障,它将会失败。例如,

[!]*[?]*

将捕获!?但不捕获?!(当然,包含单个字符的字符类只相当于该单个字符,因此您可以说!*?*)。

您可以改为使用包含要捕获的所有符号的单个字符类。一旦你看到一个字母数字字符旁边的一个,你就完成了,所以你不需要正则表达式来匹配整个输入行。

grep -v '[[:alnum:]][][!"#$%&'"'"'()*+,./:;<=>?@\^_`{|}~]' filename

还要注意表达式如何在单引号中,以便shell不会干扰这里的许多元字符。为了使单引号字符串包含文字单引号,我暂时分成双引号字符串;请参阅here获取解释(我称之为#34;跷跷板引用&#34;)。

在字符类中,如果类需要包含],则它必须位于枚举列表的开头;为了对称性和成语,我还在它旁边移动了[

此外,正如Jonathan Leffler所指出的,POSIX字符类名称需要在字符类中;因此,要匹配属于[:alnum:]命名集的一个字符,请说[[:alnum:]]。 (这意味着您可以组合集合,因此[-[:alnum:].]涵盖字母数字加上短划线和句号。)

如果您需要将其限制为仅匹配第一个字段,请将[[:alnum:]]更改为^[[:alnum:]]\+

没有意识到a*b*c*匹配任何是一个常见的新手错误。您希望避免编写一个表达式,其中所有元素都是可选的,因为它将匹配每个可能的字符串。关注你想要匹配的内容(在你的情况下,标点字符的长列表),然后如果你真的需要,可以在它周围添加可选的上下文位;但是你需要的越少,它运行得越快,看它的作用就越容易。作为一个快速的经验法则,a*bc*实际上恰好等同于b - 可能也没有指定前导或尾随可选表达式,因为它们不会影响要匹配的内容。 / p>

答案 1 :(得分:0)

从表面上看,您正在寻找空格字空间编号&#39;架构,假设&#39;字&#39;是一个字母数字,可选地后跟零或一次出现的零个或多个字母数字或标点字符,并以字母数字&#39;和&#39;空格&#39;结尾。是一个或多个空格&#39;和&#39;数字&#39;是一个或多个数字&#39;。

grep -E(又名egrep)而言:

grep -E '[[:alnum:]]([[:alnum:][:punct:]]*[[:alnum:]])?[[:space:]]+[[:alnum:]]([[:alnum:][:punct:]]*[[:alnum:]])?[[:space:]]+[[:digit:]]+'

包含:

[[:alnum:]]([[:alnum:][:punct:]]*[[:alnum:]])?

检测到包含字母数字的任何标点符号的单词,并且:

[[:space:]]+
[[:digit:]]+

寻找一个或多个空格或数字。

使用温和扩展的数据文件,这会产生:

$ cat data
example for 1
useful when 1
for. However 1
,boy wonder 1
,hary-horse wondered 2
O'Reilly Books 23
Coelecanths, Dodos Etc 19
$ grep -E '[[:alnum:]]([[:alnum:][:punct:]]*[[:alnum:]])?[[:space:]]+[[:alnum:]]([[:alnum:][:punct:]]*[[:alnum:]])?[[:space:]]+[[:digit:]]+' data
example for 1
useful when 1
,boy wonder 1
,hary-horse wondered 2
O'Reilly Books 23
Coelecanths, Dodos Etc 19
$

根据需要删除for. However 1行。