我需要使用sed / awk来获得所需的输出
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
任何帮助将不胜感激。
您可以使用
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=
字段可以按任意顺序 – 我必须读取文件两次。 您可以将其滚动到这样的脚本中:
#!/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
用s/old/new
替换old
-
-r
使用ERE -
-n
在我们要求之前不打印(这只是取出空行) -
[,\|]
匹配,
或文字|
-
([0-9]+)
稍后保存的一些数字 -
\1
反向保存模式 -
tee
写入文件并打印到stdout也可以检查它 -
> somefile
将输出重定向到somefile
而不是stdout -
paste -d ' ' file2 file3
使用空格作为分隔符,在file2的列之后粘贴file3的列。 -
rm file2 file3
删除file2和file3
使用awk
假设您的数据位于名为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
也可以看看
-
awk
入门 -
BEGIN
模式 - 关联数组
-
split
function -
printf
语句 -
NF
变量 -
FS
变量
在上面的代码中, map
变量是一个关联数组。 我称之为地图,因为它通常被称为其他语言的地图(Java中的HashMap,Ruby中的Hash或Python中的Dictionary)。
一个衬垫并不总是很好:
$ 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
替换old
-
[|,]
匹配|
或者,
-
\(11=[^|]*\)
匹配除|
以外的任何数字11=
,保存11=whatever
以后用作\1
-
.*
任意数量的任何字符 -
\(|38=[^|]*|\)
保存|38=whatever|
以后用作\2
-
\2\1|
替换中的反向引用(这使得字段保持一致,因此我们可以在下一个命令中处理它们) -
;
分隔命令,就像在shell中一样 -
Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.*
匹配此模式(现在我们已将其清理干净了)再次保存我们想要在\(parentheses\)
重复使用的部分 -
Orderid-\1 38= \2 Clientid=\3
替换为\1
\2
和\3
反向引用我们用\(\)
保存的数字
Perl解决方案:
作为单线:
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