Разделяющее значение в awk

#awk #sed

#awk #sed

Вопрос:

Я застрял с подходом, требующим разделения значения до / и после / Вот содержимое файла:

 Min/Max Inference Time : 70 ms / 290 ms
 Average Inference Time : 90 ms
  

Ожидаемый результат:

 Min : 70
Max : 290
  

Вот что я пробовал:

 cat scores.csv | awk '///' | sed 's/ms//g'| awk 'BEGIN{FS=":"}{print $2}'
  

Но я не знаю, как разделить значение до / и после / для ожидаемого результата выше.

Ответ №1:

Попробуйте awk с несколькими разделителями

 $ echo "Min/Max Inference Time : 70 ms / 290 ms" | 
awk -F"[/ ] " ' { print $1, ":", $(NF-3); print $2,":",$(NF-1) } '
Min : 70
Max : 290
$
  

ПРАВКА 1: FS не должна меняться

 $ echo "Min/Max Inference Time : 70 ms / 290 ms" | awk -F: -v OFS=":" ' {  split($1,a,"[ /] "); split($2,b,"ms|/"); print a[1],b[1]; print a[2],b[3] } '
Min: 70
Max: 290
$
  

ПРАВКА2:

 $ awk -F: -v OFS=":" ' { if(///) {  split($1,a,"[ /] "); split($2,b,"ms|/"); print a[1],b[1]; print a[2],b[3] } else { print } }' scores.csv
Min: 70
Max: 290
 Average Inference Time : 90 ms
$
  

с помощью Perl,

 $ perl -lne  ' /(. ?)/(. ?)s . ?(d ). ?(d )/ ? print $1,": ",$3,"n",$2,": ",$4 : print ' scores.csv
Min: 70
Max: 290
 Average Inference Time : 90 ms
$
  

Комментарии:

1. Я не хочу менять разделитель полей : , поскольку другие оценки зависят

2. вы имеете в виду .. разделитель выходных данных?.. можете ли вы использовать дополнительные образцы?

3. Не осталось входных FS :

4. Ожидаемый результат отсутствует, смотрите дополнительные примеры выше в моем сообщении

5. @Arya.. Я также добавил решение на Perl .. оба результата совпадают с викториями

Ответ №2:

Вы можете использовать одну sed команду:

 sed -E 's,.*b([0-9] [[:blank:]]*ms)[[:blank:]]*/[[:blank:]]*([0-9] [[:blank:]]*ms).*,Min : 1nMax : 2,'   scores.csv  >  new_scores.csv 
  

Смотрите онлайн-демонстрацию sed

Сведения о шаблоне

  • .*b — любые символы от 0 , как можно больше, вплоть до границы слова, за которой следуют последующие шаблоны
    • ([0-9] [[:blank:]]*ms) — Группа 1: 1 или более цифр, 0 пробелы, ms подстрока
    • [[:blank:]]*/[[:blank:]]* — a / заключенный в 0 или более пробелов
    • ([0-9] [[:blank:]]*ms) — Группа 2: 1 или более цифр, 0 пробелов, ms подстрока
    • .* — остальная часть строки.

Шаблон замены — это Min : 1nMax : 2 , где 1 относится к тексту, записанному с помощью группы 1, и 2 относится к тексту, записанному с помощью группы 2.

Ответ №3:

Не могли бы вы, пожалуйста, попробовать следующее. Просто установите правильные FS (разделители полей) для каждой строки и затем распечатайте их (БЕЗ манипуляций с данными и т.д.)

 awk -F"Inference Time : |/| ms" -v OFS=" : " 'FNR==1{$1=$1;print $1,$3 ORS $2,$5}' Input_file
  

Объяснение: Теперь добавляю объяснение для приведенного выше кода.

 awk -F"Inference Time : |/| ms" -v OFS=" : " '     ##Setting field separator as string Inference Time :  OR / OR ms for all lines and setting OFS as space colon space here.
FNR==1{                                            ##Checking condition if line is 1st line then do following.
  $1=$1                                            ##Re-setting $1=$1 to reflect value of OFS here.
  print $1,$3 ORS $2,$5                            ##Printing values of $1,$3 then ORS with $2,$5 here as per OP ask.
}                                                  ##Closing BLOCK for FNR==1 condition here.
'  Input_file                                      ##Mentioning Input_file name here.
  

Вывод будет следующим.

 Min : 70
Max  :  290
  

Комментарии:

1. @Arya, не могли бы вы, пожалуйста, проверить этот ответ и дать мне знать, если это поможет, добавил правильное объяснение и здесь.

Ответ №4:

первое, что вы могли бы разделить пробелом и косой чертой. И посмотрите на каждый элемент:

 awk -F'[/ ]' '{ for (i = 1; i <= NF;   i) print i ": " $i}' scores.csv
1: Min
2: Max
3: Inference
4: Time
5: :
6: 70
7: ms
8:
9:
10: 290
11: ms
  

после этого вы берете нужные элементы:

 awk -F'[/ ]' '{ print "Min : " $6; print "Max : " $10 }' scores.csv
Min : 70
Max : 290