Grep表示不以" //"开头的行

时间:2016-03-20 06:31:05

标签: regex bash grep

我正在尝试但是没有为grep写一个正则表达式而不是以" //"开头的行(即C ++风格的评论)。我知道" grep -v"选项,但我试图学习如何单独使用正则表达式来解决这个问题。 我已经搜索过并找到了各种答案,可以选择不用字符开头的线条,甚至还有一个关于如何为不用字符串开头的线条进行grep的答案,但是我可以找到答案。我无法根据我的情况调整这些答案,而且我不明白我的错误是什么。

> cat bar.txt
hello
//world
> cat bar.txt | grep "(?!\/\/)"
-bash: !\/\/: event not found

我不确定这个"事件没有找到"是关于。我找到的答案之一使用了paren-question mark-exclamation-string-paren,我在这里做过,但仍然失败了。

> cat bar.txt | grep "^[^\/\/].+"
(no output)

我发现另一个答案在方括号内使用了插入符号,并解释说这种语法意味着&#34;搜索方括号(除了插入符号)之外的缺失。我认为&#34;。+&#34;意味着&#34;一个或多个任何东西&#34;,但我不确定这是否正确,如果它是正确的,它区别于&#34;。*&#34; < / p>

简而言之:我如何构造一个正则表达式来传递给grep以搜索不以&#34; //&#34;开头的行。 ?

更具体地说,我正在尝试搜索包含&#34; #include&#34;不在&#34; //&#34;。

之前

谢谢。

6 个答案:

答案 0 :(得分:2)

  1. 您正在使用负面预测,这是PCRE功能,需要-P选项
  2. 你的负面前瞻在没有开始锚定的情况下无法工作
  3. 这当然需要gnu-grep
  4. 您必须使用单引号在正则表达式中使用!,否则会尝试使用正则表达式!之后的文本进行历史记录扩展,原因是!\/\/: event not found错误。
  5. 所以你可以使用:

    grep -P '^(?!\h*//)' file
    hello
    

    \h匹配0个或更多水平空格。

    如果没有-P或非gnu grep,您可以使用grep -v

    grep -v '^[[:blank:]]*//' file
    hello
    

答案 1 :(得分:2)

要找到#include(或// ...)之前没有的/*行,您可以使用:

grep '^[[:space:]]*#[[:space:]]*include[[:space:]]*["<]'

正则表达式查找行的开头,可选空格,#,可选空格,include,可选空格以及"<。它会找到除#include之类的行以外的所有#include MACRO_NAME行,这些行是合法但很少见的,以及如下所示的滚动案例:

#/*comment*/include/*comment*/<stdio.h>
#\
include\
<stdio.h>

如果您必须处理包含此类符号的软件,​​(a)您有同情心,并且(b)在搜索#include行之前将代码修改为更正统的样式。它会发现误报,例如:

/* Do not include this:
#include <does-not-exist.h>
*/

你可以省略最后的[[:space:]]*["<]而且混淆的可能性很小,然后会选择宏名称变体。

要查找不以双斜杠开头的行,请使用-v(以反转匹配)和'^//'以在行的开头查找斜杠:

grep -v '^//'

答案 2 :(得分:2)

第一行告诉您问题来自bash(您的shell)。 Bash找到!并尝试将您输入的最后一个注入\/\/的命令。为避免这种情况,您需要转义!或使用单引号。有关!的示例,请尝试!cat,它将执行您输入的cat开头的最后一个命令。

您不需要逃避/,它在正则表达式中没有特殊含义。您也不需要编写复杂的正则表达式来反转匹配。相反,只需向grep提供-v参数。大部分时间都比较简单。而且你也不需要把文件抓到grep。只需给grep文件名。例如

grep -v "^//" bar.txt | grep "#include"

如果您真的忙于使用正则表达式,那么一个简单的表达式就像(匹配字符串^的开头,任意数量的空格[[:space:]]*,恰好是两个反斜杠{{1 },任意数量的任何字符/{2},后跟.*):

#include

答案 3 :(得分:0)

您必须使用-P(perl)选项:

cat bar.txt | grep -P '(?!//)'

答案 4 :(得分:0)

对于不以“//”开头的行,您可以使用(^[^/]{2}.*$)

答案 5 :(得分:0)

如果您不喜欢grep -v,那么您可以使用awk:

awk '!/^\/\//' file

由于awk支持复合条件而不仅仅是regexp,因此通常更容易指定要与awk匹配的内容而不是grep,例如使用grep:

按任意顺序搜索ab
grep -E 'a.*b|b.*a`

与awk:

awk '/a/ && /b/'