如何在两个特殊字符后 grep 文本?

如何在两个特殊字符后 grep 文本?

我想 grep >&后面的数据|。我使用了这个命令:

grep -o '  |.*$'| cut -c5-

但它只是给出了以下数据|

                                                              > Aminobenzoate
Asthma                                                        | Atrazine
Autoimmune thyroid disease                                    | Bacterial
B cell receptor signaling pathway                             | Benzoate
Bile secretion                                                | beta-Lactam
                                                              > Biosynthesis
Caffeine metabolism                                           | Caprolactam
Calcium signaling pathway                                     | Carbapenem

期望输出:

Aminobenzoate
Atrazine
Bacterial
Benzoate
beta-Lactam
Biosynthesis
Caprolactam
Carbapenem

答案1

我建议使用sed

sed 's/.*[|>] *//'

这适用于您的示例,但您可能需要对其进行调整,具体取决于如何处理没有任何|或 的行>。如果应完全删除这些行,请使用

sed -n 's/.*[|>] *//p'

这意味着默认不输出(选项),但如果命令可以执行替换,则-n打印一行(p) 。s

答案2

awk也可以使用。您可以使用多个字段分隔-F符来awk同时获得>|。还可以使用sub选项在打印匹配列时清除文本前的第一个前导空格:

 awk -F'[>|]' '{sub(/^\ /, "",$2); print $2}' file.txt

答案3

使用 awk:

awk -F'[>|]' '{print$2}' input.txt | awk -F' ' '{print$1}'

或者

建议来自谢尔盖·科洛佳日内

awk -F'[>|]' '{print substr($2,2)}' input.txt

答案4

Perl

下面是一个可以完成这个工作的 perl 单行代码:

$ perl -ne 's/^.*[|>]\ //;print' inp.txt                                                
Aminobenzoate 
Atrazine 
Bacterial 
Benzoate 
beta-Lactam 
Biosynthesis 
Caprolactam 
Carbapenem

或者更短,如建议的那样马蒂贾·纳利斯在评论中

perl -pe 's/^.*[|>]\ //' inp.txt 

它基本上获取并删除从字符串开头到 或 的所有内容|>然后打印内容。


带分组的替代 sed

如果你还没有注意到,这里所有的答案都是基于删除领先的信息。我们还可以做的是团体我们想要的,并用它替换整行。重点不是主要信息,而是我们真正想要在输出中得到的东西。

就拿这个为例sed

$ sed 's/^.*[>|] \(.*$\)/\1/' inp.txt                                                     
Aminobenzoate 
Atrazine 
Bacterial 
Benzoate 
beta-Lactam 
Biosynthesis 
Caprolactam 
Carbapenem

实际情况是\(,里面的内容\)将被视为一个整体,并通过 引用。此命令基本上表示“将或\1后面的内容 加上一个空格并将其作为一个组,并用我们放入该组的内容替换整行。>|\1


Python

虽然 Python 脚本可能有点长,但它们通常更易读、更清晰。以下是我们可以使用 Python 3 脚本执行的操作:

#!/usr/bin/env python3
import sys
import re
with open(sys.argv[1]) as fd:
    for line in fd:
        print(re.split("<|>|\|",line.strip())[1].strip())

这里的关键思想如下:

  • 我们打开命令行参数提供的任何文件
  • 我们遍历文件的每一行
  • 使用re.split()函数,我们将每行拆分成列表,使用>|>作为分隔符。
  • 然后我们提取该列表中的第二个([1]列表中的索引,因为列表从 0 的索引开始)项,并使用strip()函数删除前导和尾随空格。
  • 所有这些操作re.split()和列表提取都发生在print()函数内,因此一旦完成所有这些操作,我们就会得到所需的输出字符串,然后继续处理下一行

如果我们愿意,我们可以把所有东西都放到一行代码里,像这样:

$ python -c 'import re,sys;print("\n".join([ re.split("<|>|\|",l.strip())[1].strip() for l in sys.stdin]))' < inp.txt    
Aminobenzoate
Atrazine
Bacterial
Benzoate
beta-Lactam
Biosynthesis
Caprolactam
Carbapenem

其他补充:

  • 如果这确实是一个diff输出Ravexina 的回答表明我们总是可以通过添加方括号 将其包含<在此处给出的所有表达式中。因此我们将得到:<
    • perl -pe 's/^.*[|><]\ //;' inp.txt
    • sed 's/^.*[><|] \(.*$\)/\1/' inp.txt
    • Python 解决方案是在考虑到这一点之后编写的,因此该解决方案已经包括<

相关内容