AWK: ¿cómo extraer un patrón entre 2 separadores de campos personalizados independientemente de la posición del patrón en la línea?

AWK: ¿cómo extraer un patrón entre 2 separadores de campos personalizados independientemente de la posición del patrón en la línea?

Aquí hay un fragmento de una línea en el archivo:

LN=FINE FOODS & PHARMACEUTICALS NTM, MIC=XAIM, RIC=FF.MI, SG=MA1

Estoy interesado en extraer el valor de la etiqueta "MIC", es decir, el resultado que deseo es:

XAIM

Toda la línea es bastante larga:

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}

La posición en la línea de la etiqueta "MIC" no siempre es la misma.

Leí bastantes tutoriales y parece que todas sus soluciones implican crear separadores de campo personalizados y luego extraer el patrón deseado utilizando la posición del patrón en la línea.

Por ejemplo, intenté seguir el ejemplo dado eneste hilo, es decir, utilicé este código para extraer el valor de la etiqueta "MIC":

awk 'BEGIN {FS="MIC=|,"} {print $2}' input.txt

Obtuve el siguiente resultado:

GTPID=144115188076657542

Si verifica el ejemplo de línea completa que proporcioné anteriormente, el resultado es el valor de la segunda etiqueta "GTPID" que tiene el símbolo "=". Al principio pensé que eso {FS="MIC=|,"}significaba "crear dos separadores de campos personalizados, siendo el primero MIC=y el segundo ,y, por alguna razón, esperaba que eso {print $2}imprimiera lo que hubiera entre esos dos separadores de campos.

Pero, obviamente, el código anterior imprime el valor de cualquier patrón que contenga el símbolo "=" y que sea el segundo en la línea.

¿Cómo extraigo el valor que está entre MIC=y ,entonces?

Respuesta1

Siempre que tenga pares nombre=valor en sus datos, es mejor crear primero una matriz que capture esa asignación ( f[]a continuación) y luego podrá acceder a los campos que desee por su(s) nombre(s), por ejemplo:

$ awk -F'[=,] *' '{for (i=1;i<NF;i+=2) f[$i]=$(i+1); print f["MIC"]}' file
XAIM

Mire lo fácil que es adaptarse a los valores de prueba, imprimir otros campos en cualquier orden, 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

Respuesta2

$ sed -n 's/.* MIC=\([^,}]*\).*/\1/p' file
XAIM

Esto se utiliza sedpara hacer coincidir la cadena  MIC=SOMETHING,o MIC=SOMETHING}y reemplaza toda la línea con la SOMETHINGcadena. Todos los demás datos se descartan.


$ tr ',' '\n' <file | awk -F '=' '$1 == " MIC" { print $2 }'
XAIM

Esto primero reemplaza todas las comas por nuevas líneas y luego se ejecuta awkcon un =carácter como delimitador de campo. Cuando el primer campo es igual a  MIC, se imprime el segundo campo.


$ awk -F ',' '{ for (i = 1; i <= NF; ++i) if (sub(" MIC=","",$i)) print $i }' file
XAIM

Esto solo usa awky trata la entrada como campos separados por comas. Itera sobre todos los campos, y cuando un campo comienza con la cadena  MIC=, esa cadena se elimina del campo y el resto se imprime.


Si el archivo hubiera estado en formato JSON (creo que es posible que hayas transformado los datosdeJSON en algún momento, ya que la mayoría de las API REST devuelven DATOS con formato JSON, y estos datos parecen estar relacionados con los mercados de valores financieros):

{
  "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
}

entonces jqhubiera sido más fácil:

$ jq -r '.MIC' file1
XAIM

Respuesta3

Con grepy cut. Úselo grep -opara tomar osolo los datos coincidentes, busque el campo y el valor solicitados. Introduzca eso en cut, utilizándolo =como separador de campos, y tome el segundo campo:

$ grep -o 'MIC=[^,]*' input | cut -d= -f2
XAIM

Con sed. Busque el par campo/valor solicitado, utilice ()y \1para extraer el subpatrón coincidente:

$ sed -nE 's/^.*MIC=([^,]+).*$/\1/;p' input
XAIM
# or, alternatively,
$ sed -n 's/^.*MIC=\([^,]*\).*$/\1/;p' input
XAIM

Con awk. Establezca el separador de campos y el separador de registros en =y ,respectivamente. Para el registro con el patrón coincidente, imprima el segundo campo (es decir, el valor):

$ awk 'BEGIN { FS="="; RS=","; } $1 ~ /MIC/ { print $2 }' input
XAIM

Respuesta4

dominio

 awk -F "," '{for(i=1;i<=NF;i++){if($i ~ /MIC/){gsub(/.*=/,"",$i);print $i}}}' 

Nombre del archivo

producción

XAIM

información relacionada