AWK: Wie extrahiere ich ein Muster zwischen zwei benutzerdefinierten Feldtrennzeichen, unabhängig von der Position des Musters in der Zeile?

AWK: Wie extrahiere ich ein Muster zwischen zwei benutzerdefinierten Feldtrennzeichen, unabhängig von der Position des Musters in der Zeile?

Hier ist ein Ausschnitt einer Zeile in der Datei:

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

Ich bin daran interessiert, den Wert des Tags „MIC“ zu extrahieren, d. h. meine gewünschte Ausgabe ist:

XAIM

Die ganze Zeile ist ziemlich lang:

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}

Die Position des Tags „MIC“ in der Zeile ist nicht immer gleich.

Ich habe mir ziemlich viele Tutorials durchgelesen und es scheint, dass alle Lösungen darin bestehen, benutzerdefinierte Feldtrennzeichen zu erstellen und dann anhand der Position des Musters in der Zeile ein gewünschtes Muster zu extrahieren.

Ich habe beispielsweise versucht, dem Beispiel ausdieser Thread, und zwar habe ich diesen Code verwendet, um den Wert aus dem Tag „MIC“ zu extrahieren:

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

Ich habe die folgende Ausgabe erhalten:

GTPID=144115188076657542

Wenn Sie das gesamte Zeilenbeispiel überprüfen, das ich oben bereitgestellt habe, ist die Ausgabe der Wert des zweiten Tags „GTPID“, das das Symbol „=“ hat. Zuerst dachte ich, das {FS="MIC=|,"}bedeutet „erstelle zwei benutzerdefinierte Feldtrennzeichen, das erste ist MIC=und das zweite ist“ ,, und aus irgendeinem Grund erwartete ich, dass {print $2}alles ausgedruckt wird, was zwischen diesen beiden Feldtrennzeichen steht.

Aber offensichtlich druckt der obige Code den Wert des Musters, das das Symbol "=" enthält, das zufällig an zweiter Stelle in der Zeile steht.

Wie extrahiere ich einen Wert, der zwischen MIC=und ,dann liegt?

Antwort1

Wenn Ihre Daten Name=Wert-Paare enthalten, sollten Sie am besten zuerst ein Array erstellen, das diese Zuordnung erfasst ( f[]siehe unten). Anschließend können Sie einfach über den Namen auf die gewünschten Felder zugreifen, z. B.:

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

Sehen Sie, wie einfach es ist, dies an Testwerte anzupassen, andere Felder in beliebiger Reihenfolge auszudrucken usw.:

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

Antwort2

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

Dies sedwird zum Abgleichen der Zeichenfolge  MIC=SOMETHING,oder verwendet MIC=SOMETHING}und ersetzt die gesamte Zeile durch die SOMETHINGZeichenfolge. Alle anderen Daten werden verworfen.


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

Dabei werden zunächst alle Kommas durch Zeilenumbrüche ersetzt und dann awkmit einem =Zeichen als Feldtrennzeichen ausgeführt. Wenn das erste Feld gleich ist  MIC, wird das zweite Feld gedruckt.


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

Dabei werden die Eingaben nur awkals durch Kommas getrennte Felder verwendet und behandelt. Es werden alle Felder durchlaufen, und wenn ein Feld mit der Zeichenfolge beginnt  MIC=, wird diese Zeichenfolge aus dem Feld entfernt und der Rest gedruckt.


Wenn die Datei im JSON-Format gewesen wäre (ich denke, Sie hätten die Daten möglicherweise transformiertausJSON irgendwann, da die meisten REST-APIs DATEN im JSON-Format zurückgeben und diese Daten mit den Finanzmärkten in Zusammenhang zu stehen scheinen):

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

dann jqwäre es am einfachsten gewesen:

$ jq -r '.MIC' file1
XAIM

Antwort3

Mit grepund cut. Verwenden Sie , grep -oum onur die übereinstimmenden Daten zu übernehmen, suchen Sie nach dem angeforderten Feld und Wert. Geben Sie das an weiter cut, verwenden Sie es =als Feldtrennzeichen, und übernehmen Sie das zweite Feld:

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

Mit sed. Suchen Sie nach dem gewünschten Feld/Wert-Paar und extrahieren Sie mit ()und das passende Untermuster:\1

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

Mit awk. Setzen Sie den Feldtrenner und den Datensatztrenner auf =bzw. ,. Drucken Sie für den Datensatz mit dem übereinstimmenden Muster das zweite Feld (also den Wert):

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

Antwort4

Befehl

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

Dateiname

Ausgabe

XAIM

verwandte Informationen