Мне нужно использовать 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 ответа
Ты можешь использовать
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
Вы получите свой вывод на стандартный вывод - перенаправьте, как вам угодно.
Я не могу получить это в одну строку (хотя кто-то, очевидно, может), так как 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использовать ERE-nне печатайте, пока мы не спросим (это просто уберет пустые строки)[,\|]матч,ИЛИ буквальный|([0-9]+)некоторые цифры, чтобы сохранить на потом\1обратная ссылка на сохраненный шаблонteeзаписать в файл и распечатать на стандартный вывод, чтобы вы могли проверить его> somefileперенаправить вывод наsomefileвместо стандартного выходаpaste -d ' ' file2 file3вставьте столбцы file3 после столбцов file2, используя пробел в качестве разделителя.rm file2 file3удалить файл2 и файл3
Использование 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функцияprintfзаявлениеNFпеременнаяFSпеременная
В приведенном выше коде map Переменная является ассоциативным массивом. Я назвал это картой, потому что она обычно называется картой на других языках (HashMap в Java, Hash в Ruby или Dictionary в Python).
Одни лайнеры не всегда хороши:
$ 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 решение:
Как однострочник:
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