Aqui está um fragmento de uma linha no arquivo:
LN=FINE FOODS & PHARMACEUTICALS NTM, MIC=XAIM, RIC=FF.MI, SG=MA1
Estou interessado em extrair o valor da tag "MIC", ou seja, minha saída desejada é:
XAIM
A linha inteira é bastante longa:
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}
A posição na linha da tag “MIC” nem sempre é a mesma.
Eu li alguns tutoriais e parece que todas as suas soluções envolvem a criação de separadores de campos personalizados e a extração de um padrão desejado usando a posição do padrão na linha.
Por exemplo, tentei seguir o exemplo dado emeste tópico, ou seja, usei este código para extrair o valor da tag "MIC":
awk 'BEGIN {FS="MIC=|,"} {print $2}' input.txt
Eu obtive a seguinte saída:
GTPID=144115188076657542
Se você verificar todo o exemplo de linha que forneci acima, a saída será o valor da segunda tag "GTPID" que possui o símbolo "=". No começo eu estava pensando que isso {FS="MIC=|,"}
significava "criar dois separadores de campos personalizados, sendo o primeiro MIC=
e o segundo ,
e, por algum motivo, eu esperava que isso {print $2}
imprimisse o que quer que estivesse entre esses dois separadores de campos.
Mas obviamente o código acima imprime o valor de qualquer padrão que contenha o símbolo "=" que seja o segundo na linha.
Como faço para extrair o valor entre MIC=
e ,
então?
Responder1
Sempre que você tiver pares nome=valor em seus dados, é melhor primeiro criar um array que capture esse mapeamento ( f[]
abaixo) e então você pode acessar os campos que desejar pelo(s) nome(s), por exemplo:
$ awk -F'[=,] *' '{for (i=1;i<NF;i+=2) f[$i]=$(i+1); print f["MIC"]}' file
XAIM
Veja como é fácil adaptar-se aos valores de teste, imprimir outros campos em qualquer ordem, etc.:
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
Responder2
$ sed -n 's/.* MIC=\([^,}]*\).*/\1/p' file
XAIM
Isso é usado sed
para corresponder à string MIC=SOMETHING,
ou MIC=SOMETHING}
e substitui a linha inteira pela SOMETHING
string. Todos os outros dados são descartados.
$ tr ',' '\n' <file | awk -F '=' '$1 == " MIC" { print $2 }'
XAIM
Isso primeiro substitui todas as vírgulas por novas linhas e depois é executado awk
com um =
caractere como delimitador de campo. Quando o primeiro campo é igual a MIC
, o segundo campo é impresso.
$ awk -F ',' '{ for (i = 1; i <= NF; ++i) if (sub(" MIC=","",$i)) print $i }' file
XAIM
Isso apenas usa awk
e trata a entrada como campos separados por vírgula. Ele itera em todos os campos e, quando um campo começa com string MIC=
, essa string é removida do campo e o restante é impresso.
Se o arquivo estivesse no formato JSON (acho que você pode ter transformado os dadosdeJSON em algum momento, já que a maioria das APIs REST retornam DADOS formatados em JSON, e esses dados parecem estar relacionados aos mercados de ações financeiros):
{
"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
}
então jq
teria sido mais fácil:
$ jq -r '.MIC' file1
XAIM
Responder3
Com grep
e cut
. Use grep -o
para obter o
apenas os dados correspondentes, procure o campo e o valor solicitados. Alimente isso para cut
, usando =
como separador de campo, e pegue o segundo campo:
$ grep -o 'MIC=[^,]*' input | cut -d= -f2
XAIM
Com sed
. Procure o par campo/valor solicitado, use ()
e \1
para extrair o subpadrão correspondente:
$ sed -nE 's/^.*MIC=([^,]+).*$/\1/;p' input
XAIM
# or, alternatively,
$ sed -n 's/^.*MIC=\([^,]*\).*$/\1/;p' input
XAIM
Com awk
. Defina o separador de campos e o separador de registros como =
e ,
respectivamente. Para o registro com o padrão correspondente, imprima o segundo campo (ou seja, o valor):
$ awk 'BEGIN { FS="="; RS=","; } $1 ~ /MIC/ { print $2 }' input
XAIM
Responder4
comando
awk -F "," '{for(i=1;i<=NF;i++){if($i ~ /MIC/){gsub(/.*=/,"",$i);print $i}}}'
nome do arquivo
saída
XAIM