Order:479959,60=20130624-09:45:02.046|35=D|11=884|38=723|21=1|1=30532|10=085|59=0|114=Y|56=MBT|40=1|43=Y|100=MBTX|55=/GCQ3|49=11342|54=1|8=FIX.4.4|34=388|553=2453|9=205|52=20130624-09:45:02.046|
Order:24780,100=MBTX|43=Y|40=1|34=388|553=2453|52=2013062409:45:02.046|9=205|49=11342|54=1|8=FIX.4.4|55=/GCQ3|11=405|35=D|60=20130624-09:45:02.046|56=MBT|59=0|114=Y|10=085|21=1|38=470|1=30532|
Order:799794,55=/GCQ3|49=11342|54=1|8=FIX.4.4|34=388|553=2453|9=205|52=2013062409:45:02.046|40=1|43=Y|100=MBTX|38=350|21=1|1=30532|10=085|59=0|114=Y|56=MBT|60=20130624-09:45:02.046|35=D|11=216|
Order:72896,11=735|35=D|60=2013062409:45:02.046|56=MBT|59=0|114=Y|10=085|1=30532|38=17|21=1|100=MBTX|43=Y|40=1|553=2453|9=205|52=20130624-09:45:02.046|34=388|8=FIX.4.4|54=1|49=11342|55=/GCQ3|
38=
の後の番号と11=
の後の番号を取得したいので、名前を変更する必要がありますClientid
出力は次のようになります。
Orderid-479959 38= 723 Clientid=884
Orderid-24780 38= 470 Clientid=405
Orderid-799794 38= 350 Clientid=216
Orderid-72896 38= 17 Clientid=735
どんな助けも感謝します。
データがdata.txt
というファイルにあると仮定して、script.awk
というファイルを作成し、次の内容を指定します。
BEGIN { FS="[,|]" }
NF > 0 {
for(i=1; i <= NF; i++) {
split($i, f, "[:=]")
map[f[1]] = f[2]
}
printf "Orderid-%s 38= %s Clientid=%s\n", map["Order"], map[38], map[11]
}
次に、次のコマンドを実行してデータを処理し、出力を取得します。
awk -f script.awk < data.txt
上記のコードでは、map
変数は連想配列です。通常、他の言語(JavaのHashMap、RubyのHash、またはPythonの辞書)でマップと呼ばれるため、このマップを呼び出しました。
使用できます
sed -nr 's/Order:([0-9]+),.*[,\|]38=([0-9]+)[,\|].*/Orderid-\1 38= \2/p' file | tee file2
それから
sed -nr 's/.*[,\|]11=([0-9]+)[,\|].*/Clientid=\1/p' file | tee file3
それから
paste -d ' ' file2 file3
Stdoutで出力を取得します-必要に応じてリダイレクトします。
私はそれを一行で取得することはできません( 明らかに誰かができる )11=
および38=
フィールドはどちらの順序でも構いません-ファイルを2回読み込む必要があります。次のようなスクリプトにロールできます。
#!/bin/bash
sed -nr 's/Order:([0-9]+),.*[,\|]38=([0-9]+)[,\|].*/Orderid-\1 38= \2/p' "$1" > file2
sed -nr 's/.*[,\|]11=([0-9]+)[,\|].*/Clientid=\1/p' "$1" > file3
paste -d ' ' file2 file3 > outfile
rm file2 file3
(これにより、プロセスで書き込むファイルがクリーンアップされ、最終出力がファイルoutfile
に書き込まれます)
chmod u+x script
./script file
file2
およびfile3
現在のディレクトリにこれらの名前の既存のファイルがある場合は、スクリプトで!s/old/new
old
をnew
に置き換えます-r
EREを使用-n
私たちが尋ねるまで印刷しない(これは空の行を取り出すだけだ)[,\|]
一致,
ORリテラル|
([0-9]+)
後で保存するためのいくつかの数字\1
保存されたパターンへの後方参照tee
ファイルに書き込み、stdoutに出力して確認できるようにします> somefile
出力をstdoutではなくsomefile
にリダイレクトしますpaste -d ' ' file2 file3
区切り文字としてスペースを使用して、file2の列の後にfile3の列を貼り付けます。rm file2 file3
file2とfile3を削除しますライナーの1つが常に良いとは限りません。
$ sed 's/[|,]\(11=[^|]*\).*\(|38=[^|]*|\).*/\2\1|/; s/Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.*/Orderid-\1 38= \2 Clientid=\3/' foo
Orderid-479959 38= 723 Clientid=884
Orderid-24780 38= 470 Clientid=405
Orderid-799794 38= 350 Clientid=216
Orderid-72896 38= 17 Clientid=735
s/old/new/
old
をnew
に置き換えます[|,]
一致|
または,
\(11=[^|]*\)
は、|
の後の11=
を除く任意の数の文字に一致し、11=whatever
として後で使用するために\1
を保存します.*
任意の数の任意の文字\(|38=[^|]*|\)
|38=whatever|
として後で使用するために\2
を保存します\2\1|
後方参照の置換(これにより、フィールドの一貫性が保たれるため、次のコマンドでそれらを処理できます);
は、シェルのようにコマンドを分離しますOrder:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.*
はこのパターンに一致し(クリーンアップ済み)、\(parentheses\)
で再利用したい部分を再び保存します\(\)
で保存した番号へのOrderid-\1 38= \2 Clientid=\3
\1
\2
および\3
後方参照による置換ワンライナーとして:
Perl -a -F'[:|,]' -lne 'next if $_ =~ /^$/;printf("%sid-%s ",$F[0],$F[1]);foreach(@F){$t=$_ if $_ =~ "38=";$id=$_ if $_ =~ "11="};$id =~s/11=//;printf("%s Clientid=%s\n",$t,$id)' input.txt
またはスクリプトとして:
#!/usr/bin/env Perl
use strict;
use warnings;
open(my $fh,'<',$ARGV[0]) or die $!;
while(my $line = <$fh>){
next if $line =~ /^$/;
my @words = split /[:|,]/,$line;
printf("%sid-%s ",$words[0],$words[1]);
my $t;
my $id;
foreach my $Word (@words){
$t = $Word if $Word =~ "38=";
$id=$Word if $Word =~ "11=";
$id =~ s/11=// if length($id);
}
printf("%s Clientid=%s\n", $t ,$id);
}
close($fh) or die $!;
試験結果:
$ ./parse_orders.pl ./input.txt
Orderid-479959 38=723 Clientid=884
Orderid-24780 38=470 Clientid=405
Orderid-799794 38=350 Clientid=216
Orderid-72896 38=17 Clientid=735