使用 awk

使用 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

任何帮助将不胜感激。

答案1

您可以使用

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/newold用。。。来代替new
  • -r使用 ERE
  • -n在我们询问之前不打印(这只会删除空行)
  • [,\|]匹配,或文字|
  • ([0-9]+)一些数字需要保存以供日后使用
  • \1反向引用已保存的模式
  • tee写入文件并打印到标准输出,以便您可以检查它
  • > somefile重定向输出到somefilestdout 而不是
  • paste -d ' ' file2 file3将 file3 的列粘贴到 file2 的列之后,使用空格作为分隔符。
  • rm file2 file3删除文件2和文件3

答案2

使用 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

也可以看看

在上面的代码中,map变量是一个关联数组。我将其称为 map,因为它在其他语言中通常被称为 map(Java 中为 HashMap,Ruby 中为 Hash,Python 中为 Dictionary)。

答案3

一句话并不总是好的:

$ 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|替换中的反向引用(这使字段保持一致,以便我们可以在下一个命令中处理它们)
  • ;分隔命令,就像在 shell 中一样
  • Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.*匹配此模式(现在我们已经清理干净了)保存我们想要\(parentheses\)再次重复使用的部分
  • Orderid-\1 38= \2 Clientid=\3替换\1 \2\3反向引用我们保存的数字\(\)

答案4

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

相关内容