Вот фрагмент строки в файле:
LN=FINE FOODS & PHARMACEUTICALS NTM, MIC=XAIM, RIC=FF.MI, SG=MA1
Меня интересует извлечение значения тега «MIC», т.е. мой желаемый вывод:
XAIM
Вся строка довольно длинная:
20200403: #379 IT0005215329 {CU=EUR, GTPID=144115188076657542, II=IT0005215329, IS=18814564, LN=FINE FOODS & PHARMACEUTICALS NTM, MIC=XAIM, RIC=FF.MI, SG=MA1, SN=801670, STY=ORDINARY, TK="0.0002 to 0.1,0.0005 to 0.2,0.001 to 0.5,0.002 to 1,0.005 to 2,0.01 to 5,0.02 to 10,0.05 to 20,0.1 to 50,0.2 to 100,0.5 to 200,1 to 500,2 to 1000,5 to 2000,10 to 5000,20 to 10000,50 to 20000,100 to 50000,200", TS=FF, TY=S, UQ=1}
Положение на строке тега «MIC» не всегда одинаково.
Я прочитал довольно много руководств, и, похоже, все их решения предполагают создание пользовательских разделителей полей и последующее извлечение нужного шаблона с использованием положения шаблона на строке.
Например, я попытался следовать примеру, приведенному вэта тема, а именно я использовал этот код для извлечения значения из тега «MIC»:
awk 'BEGIN {FS="MIC=|,"} {print $2}' input.txt
Я получил следующий результат:
GTPID=144115188076657542
Если вы проверите весь пример строки, который я привел выше, то увидите, что выводом является значение второго тега «GTPID», в котором есть символ «=». Сначала я подумал, что это {FS="MIC=|,"}
означает «создать два пользовательских разделителя полей, первый из которых будет , MIC=
а второй — » ,
, и по какой-то причине я ожидал, что это {print $2}
выведет все, что находится между этими двумя разделителями полей.
Но очевидно, что приведенный выше код выводит значение любого шаблона, содержащего символ «=», который оказывается вторым в строке.
Как извлечь значение, которое находится между MIC=
и ,
?
решение1
Всякий раз, когда в ваших данных есть пары имя=значение, лучше всего сначала создать массив, который фиксирует это сопоставление ( f[]
ниже), а затем вы можете просто получить доступ к любым полям по их имени(ям), например:
$ awk -F'[=,] *' '{for (i=1;i<NF;i+=2) f[$i]=$(i+1); print f["MIC"]}' file
XAIM
Посмотрите, как легко это адаптировать для проверки значений, печати других полей в любом порядке и т. д.:
awk -F'[=,] *' '
{ for (i=1;i<NF;i+=2) f[$i]=$(i+1) }
(f["MIC"] == "XAIM") && (f["LN"] ~ /FOOD/){ print f["SG"], f["RIC"] }
' file
MA1 FF.MI
решение2
$ sed -n 's/.* MIC=\([^,}]*\).*/\1/p' file
XAIM
Это используется sed
для сопоставления строки MIC=SOMETHING,
или MIC=SOMETHING}
и заменяет всю строку на SOMETHING
строку. Все остальные данные отбрасываются.
$ tr ',' '\n' <file | awk -F '=' '$1 == " MIC" { print $2 }'
XAIM
Сначала это заменяет все запятые на новые строки, а затем выполняется awk
с =
символом в качестве разделителя полей. Когда первое поле равно MIC
, печатается второе поле.
$ awk -F ',' '{ for (i = 1; i <= NF; ++i) if (sub(" MIC=","",$i)) print $i }' file
XAIM
Это использует awk
и обрабатывает только ввод как поля, разделенные запятыми. Он выполняет итерацию по всем полям, и когда поле начинается со строки MIC=
, эта строка удаляется из поля, а остаток печатается.
Если бы файл был в формате JSON (я думаю, вы могли преобразовать данныеотJSON в какой-то момент, поскольку большинство REST API возвращают ДАННЫЕ в формате JSON, и эти данные, по-видимому, связаны с финансовыми фондовыми рынками):
{
"CU": "EUR",
"GTPID": 144115188076657540,
"II": "IT0005215329",
"IS": 18814564,
"LN": "FINE FOODS & PHARMACEUTICALS NTM",
"MIC": "XAIM",
"RIC": "FF.MI",
"SG": "MA1",
"SN": 801670,
"STY": "ORDINARY",
"TK": "0.0002 to 0.1,0.0005 to 0.2,0.001 to 0.5,0.002 to 1,0.005 to 2,0.01 to 5,0.02 to 10,0.05 to 20,0.1 to 50,0.2 to 100,0.5 to 200,1 to 500,2 to 1000,5 to 2000,10 to 5000,20 to 10000,50 to 20000,100 to 50000,200",
"TS": "FF",
"TY": "S",
"UQ": 1
}
тогда jq
было бы проще всего:
$ jq -r '.MIC' file1
XAIM
решение3
С grep
и cut
. Используйте grep -o
для взятия o
только соответствующих данных, найдите запрошенное поле и значение. Передайте это в cut
, используя =
в качестве разделителя полей, и возьмите второе поле:
$ grep -o 'MIC=[^,]*' input | cut -d= -f2
XAIM
С sed
. Найдите запрошенную пару поле/значение, используйте ()
и \1
для извлечения соответствующего подшаблона:
$ sed -nE 's/^.*MIC=([^,]+).*$/\1/;p' input
XAIM
# or, alternatively,
$ sed -n 's/^.*MIC=\([^,]*\).*$/\1/;p' input
XAIM
С awk
. Установите разделитель полей и разделитель записей на =
и ,
соответственно. Для записи с соответствующим шаблоном выведите второе поле (т.е. значение):
$ awk 'BEGIN { FS="="; RS=","; } $1 ~ /MIC/ { print $2 }' input
XAIM
решение4
команда
awk -F "," '{for(i=1;i<=NF;i++){if($i ~ /MIC/){gsub(/.*=/,"",$i);print $i}}}'
имя файла
выход
XAIM