У меня есть файл с текстом:
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
$ sed -r 's/[^_]+_([^_]+)_.*/\1/' file
ASSET-D
STRING-H
FILE-FD
-r
Использовать ERE s/old/new/
заменить old
на new
[^_]+
некоторые символы, которые не подчеркивать (some chars)
сохранить some chars
для последующего использования .*
любое количество любых символов \1
сохраненный шаблон Можно использовать awk
со следующими параметрами:
-F "_"
- который использует _
в качестве разделителя '{print $2}'
- который печатает 2-й элемент
$ awk -F "_" '{print $2}' input_file
ASSET-D
STRING-H
FILE-FD
Если бы Вы хотите позволить другие инструменты, cut
была бы большая часть простого решения:
cut -d _ -f 2 < input.txt > output.txt
Несколько подходов жемчуга:
$ 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
для отбрасывания его так, он не печатается. Затем нам просто нужно как многие не -_
символы, поскольку мы можем найти ([^_]+
).
Как 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])
впоследствии печатает найденную строку.