Grep 与“-o”相反的选项(不是 -v)

Grep 与“-o”相反的选项(不是 -v)

我想只打印字符串中不匹配的部分。有相反的选项吗grep -o?不是grep -v因为它完全忽略包含模式的字符串。

可以说我有:

setenv var   "/home/user/dir/subdir/case"
setenv path  "/home/user/dir"

我只需要返回subdir/case,但我找不到一种简单的方法来做到这一点grep

如果grep -o仅返回匹配的字符串的一部分,是否有一个否定选项仅返回不匹配的字符串的一部分?

答案1

使用sedPerl 或 Perl,您可以删除与模式匹配的行的一部分并打印剩余的行。假设您的示例数据位于file.txt

$ sed -ne 's/^setenv var *//p' < file.txt 
"/home/user/dir/subdir/case"

您询问的有关获取的内容实际上subdir/case需要删除两个部分,因为还有结尾引用。使用捕获组从中间获取一部分会更容易。在这里,该(.*)部分告诉sed存储此时适合的字符串部分,而\1在替换部分中则告诉替换与其匹配的所有内容。 print ( p) 命令以此处的替换 ( s///) 匹配为条件。我使用,作为分隔符,因为它/出现在模式本身中,但您可以使用任何字符。

$ sed -nEe 's,^setenv var *"/home/user/dir/(.*)".*,\1,p' < file.txt 
subdir/case

或者在 Perl 中,不替换任何内容,而只是在匹配上打印捕获的部分:

$ perl -lne 'print $1 if m,^setenv var *"/home/user/dir/(.*)",' < file.txt 
subdir/case

对于与模式不匹配的行,以上两者都不会打印任何内容。

如果您也想完整地打印这些内容,请使打印无条件(请注意前面的分号p):

$ sed -nEe 's,^setenv var *"/home/user/dir/(.*)",\1,; p' < file.txt 
subdir/case
setenv path  "/home/user/dir"

或者

$ perl -lne 's,^setenv var *"/home/user/dir/(.*)",$1,; print' < file.txt
subdir/case
setenv path  "/home/user/dir"

答案2

如果我理解正确的话,你可以使用GNU greplookbehind assertionlookahead assertion:

# return what doesn't match 'dir/' at the end of the line
# and doesn't match the final double quote '"'
$ grep -Po '(?<=dir/).*(?="$)' file
subdir/case

dir/这假设之前的“负”模式subdir/case。如果模式是完整目录:

grep -Po '(?<="/home/user/dir/).*(?="$)' file

相关内容