我想只打印字符串中不匹配的部分。有相反的选项吗grep -o
?不是grep -v
因为它完全忽略包含模式的字符串。
可以说我有:
setenv var "/home/user/dir/subdir/case"
setenv path "/home/user/dir"
我只需要返回subdir/case
,但我找不到一种简单的方法来做到这一点grep
。
如果grep -o
仅返回匹配的字符串的一部分,是否有一个否定选项仅返回不匹配的字符串的一部分?
答案1
使用sed
Perl 或 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 grep和lookbehind assertion
和lookahead 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