bash grep 模式并输出行的不匹配部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6418466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
grep a pattern and output non-matching part of line
提问by Dennis
I know it is possible to invert grep output with the -vflag. Is there a way to only output the non-matching part of the matched line? I ask because I would like to use the return code of grep (which sed won't have). Here's sort of what I've got:
我知道可以使用-v标志反转 grep 输出。有没有办法只输出匹配行的不匹配部分?我问是因为我想使用 grep 的返回码(sed 没有)。这是我所拥有的:
tags=$(grep "^$PAT" >/dev/null 2>&1)
[ "$?" -eq 0 ] && echo $tags
回答by David W.
You could use sed:
你可以使用sed:
$ sed -n "/$PAT/s/$PAT//p" $file
The only problem is that it'll return an exit code of 0 as long as the pattern is good, even if the pattern can't be found.
唯一的问题是,只要模式良好,它就会返回退出代码 0,即使找不到模式。
Explanation
解释
The -nparameter tells sednot to print out any lines. Sed's default is to print out all lines of the file. Let's look at each part of the sedprogram in between the slashes. Assume the program is /1/2/3/4/5:
该-n参数告诉sed不要打印任何行。Sed 的默认设置是打印出文件的所有行。让我们看看sed程序中斜线之间的每个部分。假设程序是/1/2/3/4/5:
/$PAT/: This says to look for all lines that matches pattern$PATto run your substitutioncommand. Otherwise,sedwould operate on all lines, even if there is no substitution./s/: This says you will be doing a substitution/$PAT/: This is the pattern you will be substituting. It's$PAT. So, you're searching for lines that contain$PATand then you're going to substitute the pattern for something.//: This is what you're substituting for$PAT. It is null. Therefore, you're deleting$PATfrom the line./p: This finalpsays to print out the line.
/$PAT/:这表示要查找与模式匹配的所有行$PAT以运行您的替换命令。否则,sed将对所有行进行操作,即使没有替换。/s/: 这表示您将进行替换/$PAT/:这是您将要替换的模式。它是$PAT。因此,您正在搜索包含的行,$PAT然后您将用模式替换某些内容。//: 这就是你要替代的$PAT。它是空的。因此,您$PAT要从该行中删除。/p: 这个 finalp说要打印出该行。
Thus:
因此:
- You tell
sednot to print out the lines of the file as it processes them. - You're searching for all lines that contain
$PAT. - On these lines, you're using the
scommand (substitution) to remove the pattern. - You're printing out the line once the pattern is removed from the line.
- 您告诉
sed不要在处理文件时打印出文件的行。 - 您正在搜索所有包含
$PAT. - 在这些行中,您使用
s命令(替换)来删除模式。 - 一旦从线条中移除图案,您就会打印出线条。
回答by Fredrik Pihl
How about using a combination of grep, sedand $PIPESTATUSto get the correct exit-status?
如何使用grep,sed和的组合$PIPESTATUS来获得正确的退出状态?
$ echo Humans are not proud of their ancestors, and rarely invite
them round to dinner | grep dinner | sed -n "/dinner/s/dinner//p"
Humans are not proud of their ancestors, and rarely invite them round to
$ echo $PIPESTATUS[1]
0[1]
The members of the $PIPESTATUSarray hold the exit status of each respective command executed in a pipe. $PIPESTATUS[0]holds the exit status of the first command in the pipe, $PIPESTATUS[1]the exit status of the second command, and so on.
$PIPESTATUS数组的成员保存在管道中执行的每个相应命令的退出状态。$PIPESTATUS[0]保存管道中第一个命令$PIPESTATUS[1]的退出状态,第二个命令的退出状态,依此类推。
回答by Ярослав Рахматуллин
Your $tags will never have a value because you send it to /dev/null. Besides from that little problem, there is no input to grep.
您的 $tags 永远不会有值,因为您将它发送到 /dev/null。除了那个小问题之外,grep 没有任何输入。
echo hello |grep "^he" -q ;
ret=$? ;
if [ $ret -eq 0 ];
then
echo there is he in hello;
fi
a successful return code is 0.
成功的返回码为 0。
...here is 1 take at your 'problem':
...这是您的“问题”中的 1 个:
pat="most of ";
data="The apples are ripe. I will use most of them for jam.";
echo $data |grep "$pat" -q;
ret=$?;
[ $ret -eq 0 ] && echo $data |sed "s/$pat//"
The apples are ripe. I will use them for jam.
... exact same thing?:
...完全相同的事情?:
echo The apples are ripe. I will use most of them for jam. | sed ' s/most\ of\ //'
It seems to me you have confused the basic concepts. What are you trying to do anyway?
在我看来,您混淆了基本概念。你到底想做什么?

