Eu preciso usar sed / awk para obter a saída desejada

4
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|

Eu quero obter o número depois de 38= e o número após 11= , que deve ser renomeado Clientid

A saída deve ser: -

Orderid-479959 38= 723 Clientid=884
Orderid-24780 38= 470 Clientid=405
Orderid-799794 38= 350 Clientid=216
Orderid-72896 38= 17 Clientid=735

Qualquer ajuda será apreciada.

    
por Sonal 03.01.2017 / 23:02

4 respostas

4

Você pode usar

sed -nr 's/Order:([0-9]+),.*[,\|]38=([0-9]+)[,\|].*/Orderid- 38= /p' file | tee file2

Então

sed -nr 's/.*[,\|]11=([0-9]+)[,\|].*/Clientid=/p' file | tee file3

Então

paste -d ' ' file2 file3

Você obtém sua saída em stdout - redirecionamento como quiser.

Eu não consigo em uma linha (embora alguém obviamente possa ) desde o 11= e 38= campos podem estar em qualquer ordem - eu tenho que ler o arquivo duas vezes. Você poderia colocá-lo em um script como este:

#!/bin/bash
sed -nr 's/Order:([0-9]+),.*[,\|]38=([0-9]+)[,\|].*/Orderid- 38= /p' "" > file2
sed -nr 's/.*[,\|]11=([0-9]+)[,\|].*/Clientid=/p' "" > file3
paste -d ' ' file2 file3 > outfile
rm file2 file3

(isso limpa os arquivos que gravamos no processo e grava a saída final em um arquivo outfile )

Uso:

  • cole o script em um arquivo vazio e salve-o
  • conceda permissão de execução: chmod u+x script
  • execute-o com o nome do seu arquivo de entrada como argumento: ./script file
  • altere file2 e file3 no script se você tiver arquivos existentes com esses nomes no diretório atual!

Explicação

  • s/old/new replace old com new
  • -r use ERE
  • -n não imprime até que nós perguntemos (isto é apenas tirar linhas vazias)
  • [,\|] correspondência , OU literal |
  • ([0-9]+) de alguns dígitos para guardar para mais tarde
  • backreference para o padrão salvo
  • tee escreve em um arquivo e imprime para o stdout também para que você possa verificá-lo
  • > somefile redireciona a saída para somefile em vez de stdout
  • paste -d ' ' file2 file3 cole as colunas do arquivo3 depois das colunas do arquivo2 usando um espaço como delimitador.
  • rm file2 file3 delete file2 e file3
por Zanna 03.01.2017 / 23:37
4

Usando o awk

Supondo que seus dados estejam em um arquivo chamado data.txt , crie um arquivo chamado script.awk e forneça o seguinte conteúdo:

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]
}

Em seguida, execute o seguinte comando para processar os dados e obter a saída.

awk -f script.awk < data.txt

Veja também

No código acima, a variável map é uma matriz associativa. Eu chamei de mapa porque é tipicamente chamado de mapa em outras linguagens (HashMap em Java, Hash em Ruby ou Dicionário em Python).

    
por Sam Gleske 04.01.2017 / 11:10
3

Um forro não é sempre legal:

$ sed 's/[|,]\(11=[^|]*\).*\(|38=[^|]*|\).*/|/; s/Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.*/Orderid- 38=  Clientid=/' 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

Explicação

  • s/old/new/ replace old com new
  • [|,] correspondência | ou ,
  • \(11=[^|]*\) corresponde a qualquer número de caracteres exceto | após 11= e economiza 11=whatever para uso posterior como
  • .* qualquer número de caracteres
  • \(|38=[^|]*|\) save |38=whatever| para uso posterior como
  • | faz referência anterior à substituição (isso torna os campos consistentes para que possamos lidar com eles no próximo comando)
  • ; separa comandos, como no shell
  • Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.* corresponde a esse padrão (agora nós o limpamos) salvando as partes que queremos reutilizar em \(parentheses\)
  • Orderid- 38= Clientid= substituição com e referência anterior aos números que salvamos com \(\)
por muru 04.01.2017 / 08:58
0

Solução Perl:

Como um marcador:

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

Ou como script:

#!/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 $!;

Resultados do teste:

$ ./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
    
por Sergiy Kolodyazhnyy 05.03.2017 / 20:48