Я должен использовать 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

Любая справка будет цениться.

4
задан 3 January 2017 в 15:53

4 ответа

Можно использовать

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 замена old с new
  • -r используйте ДО
  • -n не печатайте, пока мы не спрашиваем (это просто собирается вынуть пустые строки),
  • [,\|] соответствие , ИЛИ литерал |
  • ([0-9]+) некоторые цифры для сохранения на потом
  • \1 обратная ссылка на сохраненный шаблон
  • tee запишите в файл и печать к stdout также, таким образом, можно проверить его
  • > somefile перенаправьте вывод к somefile вместо stdout
  • paste -d ' ' file2 file3 столбцы вставки file3 после столбцов file2, использующего пространство как разделитель.
  • rm file2 file3 удалите file2 и file3
4
ответ дан 23 November 2019 в 11:42

Используя 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 переменная является ассоциативным массивом. Я назвал это картой, потому что это обычно называло карту на других языках (HashMap в Java, Хеш в Ruby или Словарь в Python).

4
ответ дан 23 November 2019 в 11:42

Лайнеры не всегда хороши:

$ 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 обратные ссылки на числа мы сохранили с \(\)
3
ответ дан 23 November 2019 в 11:42

Решение для 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
0
ответ дан 23 November 2019 в 11:42

Другие вопросы по тегам:

Похожие вопросы: