前缀搜索名称以bash输出

时间:2018-03-05 22:16:19

标签: linux bash shell awk sed

我有一个简单的egrep命令,在文本文件中搜索多个字符串,输出null或值。下面是命令和输出。

cat Output.txt|egrep -i "abc|def|efg"|cut -d ':' -f 2

输出是: -

xxx
(null)
yyy

现在,我正在尝试将我的搜索文本添加到输出中,如下所示。

abc:xxx
def:
efg:yyy

对于实现此目的或从何处开始的代码的任何帮助将不胜感激。

-Abhi

3 个答案:

答案 0 :(得分:3)

由于我不确切知道您的输入文件内容(在问题中没有正确指定),我会提出一些假设来回答您的问题。

案例1:您要查找的模式始终位于同一列

如果是这样的话,答案非常简单:

$ cat grep_file.in 
abc:xxx:uvw
def:::
efg:yyy:toto
xyz:lol:hey

$ egrep -i "abc|def|efg" grep_file.in | cut -d':' -f1,2
abc:xxx
def:
efg:yyy

grep之后只需使用您要查找的2列剪切(此处为1和2)

备注:

不要cat文件,pipe,然后grep,因为这是两次工作!你的grep命令已经读取了这个文件,所以不要读两遍,对于小文件来说可能不那么重要,但你会觉得10GB文件有所区别!

案例2:您要查找的模式不在同一列中

在这种情况下,它有点棘手,但并非不可能。有很多方法,在这里我将详细介绍awk方式:

$ cat grep_file2.in 
abc:xxx:uvw
::def:
efg:yyy:toto
xyz:lol:hey

如果您的输入文件采用此格式;你的模式可以位于任何地方:

$ awk 'BEGIN{FS=":";ORS=FS}{tmp=0;for(i=1;i<=NF;i++){tmp=match($i,/abc|def|efg/);if(tmp){print $i;break}}if(tmp){printf "%s\n", $2}}' grep_file
2.in                                                                                                                                         
abc:xxx
def:
efg:yyy

<强>说明: FS=":";ORS=FS:定义您的输入/输出字段分隔符然后在每一行上定义一个测试变量,当您到达模式时,该变量将变为true,您循环该行的所有字段,直到达到它为止如果是你打印它的情况,打破循环并打印第二个字段+一个EOL字符。 如果你不符合你的模式,你什么都不做。

如果您更喜欢sed方式,可以使用以下命令:

$ sed -n '/abc\|def\|efg/{h;s/.*\(abc\|def\|efg\).*/\1:/;x;s/^[^:]*:\([^:]*\):.*/\1/;H;x;s/\n//p}' grep_file2.in                               
abc:xxx
def:
efg:yyy

说明:

/abc\|def\|efg/{}用于过滤仅包含其中一个模式的行,然后执行块中的指令。 h;s/.*\(abc\|def\|efg\).*/\1:/;将行保存在保留空间中,并用3种模式中的一种替换该行,x;s/^[^:]*:\([^:]*\):.*/\1/;用于交换模式并保留空间并提取第二列元素。最后但并非最不重要的是,H;x;s/\n//p用于在1行上重新组合两个提取的元素并打印它。

答案 1 :(得分:1)

试试这个

$ egrep -io "(abc|def|efg):[^:]*" file

将在分隔符后打印匹配和下一个标记。

答案 2 :(得分:0)

如果我们可以假设只有两个字段,abc等将始终在第一个字段中匹配,并且在包含多个匹配的行上获得最后一个匹配是可以接受的,这非常简单{{ 1}}脚本可以工作。

sed

如果适用其他但类似的条件(例如,有三个或更多字段,但我们不关心前两个字段中的匹配),则所需的修改是微不足道的。如果没有,你真的需要澄清你的问题。