Как делают меня 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
4
задан 12 May 2017 в 04:11

6 ответов

Я предложил бы использовать sed для этого:

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

Это работает на Ваш пример, но Вы, возможно, должны адаптировать его, в зависимости от того, что сделать со строками без любого | или >. Если они должны быть удалены полностью, используйте

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

, Это означает, не производят по умолчанию (опция -n), но печатают строку (p), если эти s команда могла бы выполнить замену.

5
ответ дан 23 November 2019 в 11:35

awk может использоваться также. Можно использовать несколько разделителей полей с помощью -F с awk для получения и > и |. Также может использовать sub опция освободить сначала ведущее место, которые появляются перед текстом, когда это печатает столбцы соответствия:

 awk -F'[>|]' '{sub(/^\ /, "",$2); print $2}' file.txt
4
ответ дан 23 November 2019 в 11:35

Используя awk:

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

ИЛИ

Предложенный Sergiy Kolodyazhnyy

awk -F'[>|]' '{print substr($2,2)}' input.txt
3
ответ дан 23 November 2019 в 11:35

В первую очередь, я полагаю, что это diff -y вывод, таким образом, можно также включать < также.

Мы можем только использовать grep, чтобы сделать, это через оглядывается:

grep -Po "(?<=(\||<|>)\s).*" file.txt
  • .* Ищут что-либо любые повторенные времена.
  • (?<=(\||<|>)\s), который находится позади одного из них (| или < или >) сопровождается пространством.

более ясная версия:

grep -Po '(?<=[<|>]\s).*' file.txt
<час>

Или использование grep и cut, поскольку Вы пробовали:

grep -Eo "(<|>|\|).*" file.txt | cut -f2 -d' '
  • -E: расширенный grep
  • -o Печать только подобранные средства части
  • (<|>|\|) < или | или >.
  • .* каждая вещь & любые времена повторились

Который бриги нас к этой точке:

enter code here
> Aminobenzoate 
| Atrazine 
| Bacterial 
| Benzoate 
| beta-Lactam 
> Biosynthesis 
| Caprolactam 
| Carbapenem

затем использование cut мы получаем второе поле, которое является нашими строками, который является:

Aminobenzoate
Atrazine
Bacterial
Benzoate
beta-Lactam
Biosynthesis
Caprolactam
Carbapenem
3
ответ дан 23 November 2019 в 11:35

Наименьшее количество объема модификации от Вашей текущей команды состояло бы в том, чтобы заменить Ваше упоминание литералу | символ в Вашем regex к ссылке на класс символов, содержащий и | и >, [|>], который будет соответствовать любому из них:

grep -o '  [|>].* 

Другие исследовали awk, sed и perl реализации, но Ваш grep реализация могла также быть улучшена далее.

, Например, Вы могли избавиться от эти cut команда следующими способами:

  • при помощи Perl \K флаг: grep -Po '[>|]\s*\K.*
  • при помощи lookbehind PCRE: grep -Po '(?<=[|>]\s).*' примечание, что это будет только работать с установленной суммой пробелов между разделителем и выходным словом как механизмы PCRE, не требуется, чтобы реализовывать переменную ширину lookbehind и обычно делать нет.
| cut -c5-

Другие исследовали awk, sed и perl реализации, но Ваш grep реализация могла также быть улучшена далее.

, Например, Вы могли избавиться от эти cut команда следующими способами:

  • при помощи Perl \K флаг: grep -Po '[>|]\s*\K.*
  • при помощи lookbehind PCRE: grep -Po '(?<=[|>]\s).*' примечание, что это будет только работать с установленной суммой пробелов между разделителем и выходным словом как механизмы PCRE, не требуется, чтобы реализовывать переменную ширину lookbehind и обычно делать нет.
0
ответ дан 23 November 2019 в 11:35

Perl

Вот острота жемчуга, которая делает задание:

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

Или еще короче, как предложено Matija Nalis в комментариях

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

Другие примечания стороны:

  • если это действительно a diff вывод как ответ Ravexina предполагает, что мы можем всегда включать < во все выражения, представленные здесь путем добавления < в квадратные скобки. Таким образом мы будем иметь:
    • perl -pe 's/^.*[|><]\ //;' inp.txt
    • sed 's/^.*[><|] \(.*$\)/\1/' inp.txt
    • Решение Python было записано после того, как это стало соображением, так, чтобы решение уже включало <
3
ответ дан 23 November 2019 в 11:35

Другие вопросы по тегам:

Похожие вопросы: