Поиск линию за линией текста между первыми двумя соответствиями

У меня есть файл с текстом:

1861_ASSET-D_T_201702181000-201702181045_HN_
197895_STRING-H_T_201702181000-201702181045_HN_
14512861_FILE-FD_T_201702181000-201702181045_HN

Как я могу выделить текст между первыми и вторыми соответствиями "_" использующий egrep, awk или sed?

Я хочу иметь:

ASSET-D
STRING-H
FILE-FD
6
задан 20 February 2017 в 07:03

5 ответов

$ sed -r 's/[^_]+_([^_]+)_.*/\1/' file
ASSET-D
STRING-H
FILE-FD

Объяснение

  • -r Использовать ERE
  • s/old/new/ заменить old на new
  • [^_]+ некоторые символы, которые не подчеркивать
  • (some chars) сохранить some chars для последующего использования
  • .* любое количество любых символов
  • \1 сохраненный шаблон
10
ответ дан 23 November 2019 в 07:13

Можно использовать awk со следующими параметрами:

  • -F "_" - который использует _ в качестве разделителя
  • '{print $2}' - который печатает 2-й элемент

    $ awk -F  "_" '{print $2}' input_file
    ASSET-D
    STRING-H
    FILE-FD
    
10
ответ дан 23 November 2019 в 07:13

Если бы Вы хотите позволить другие инструменты, cut была бы большая часть простого решения:

cut -d _ -f 2 < input.txt > output.txt
9
ответ дан 23 November 2019 в 07:13

Несколько подходов жемчуга:

$ perl -F_ -lae 'print $F[1]' file 
ASSET-D
STRING-H
FILE-FD

-a заставляет жемчуг действовать как awk, разделяя каждую входную строку на символе, данном -F и сохранение каждого получающегося поля в массиве @F. Поэтому печать $F[1] распечатает 2-е поле (массивы начинают рассчитывать в 0).

Кроме того:

$ perl -pe 's/.*?_(.+?)_.*/$1/' file 
ASSET-D
STRING-H
FILE-FD

-p означает, "печатают каждую входную строку после запущения скрипта, данного -e на нем". s/from/to/ оператор замены. Это заменит from с to. Здесь, я соответствую 0 или больше символам (.*) но делая это "нежадным" (.*?); это ? заставляет его остановиться в самом коротком соответствии. Поэтому .*?_ будет соответствовать всему до 1-го _. Следующая часть, (.+?)_ соответствия один или несколько символов до следующего _ и затем мы соответствуем всему остальному до конца строки (.*). Круглые скобки "получают" соответствие и делают его доступным в заменяющей стороне оператора как $1. Поэтому все это просто заменит всю строку тем, что было в круглых скобках.


Вы могли также просто сделать это с grep:

$ grep -oP '^.*?_\K[^_]+' file 
ASSET-D
STRING-H
FILE-FD

-o означает "печать только часть каждой строки, которая соответствовала" и -P включает Perl совместимые регулярные выражения (PCRE), которые дают нам \K. \K, в свою очередь средства "игнорируют все подобранное до этой точки". Это означает, что мы можем использовать ^.*?_ к matche все до первого _ и затем используйте \K для отбрасывания его так, он не печатается. Затем нам просто нужно как многие не -_ символы, поскольку мы можем найти ([^_]+).

6
ответ дан 23 November 2019 в 07:13

Как Python один - лайнер:

python3 -c "[print(l.split('_')[1]) for l in open('f')]"

где 'f' Ваш файл, в кавычках, например:

python3 -c "[print(l.split('_')[1]) for l in open('/home/jacob/blub')]"

ASSET-D
STRING-H
FILE-FD

Объяснение

for l in open('f')

чтения f на строку, и

l.split('_')[1]

разделяет строку разделителем _, сохраняет вторую строку (индекс [1], где [0] является первым.

print(l.split('_')[1]) 

впоследствии печатает найденную строку.

6
ответ дан 23 November 2019 в 07:13

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

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