У меня есть CSV, который выводит команды time для разных программ, включая идентификатор выполнения.
Поэтому мои файлы содержат записи в следующем виде:
ID,execution_time
Пример записи:
345,0m0.047s
Мне нужен только номер выполнения и номер секунд.
Поэтому вышеупомянутая запись должна быть
345,0047 (без «0m» «.» и «s»).
[d6 ] Можно ли это достичь?Что делать, если есть минуты, а? Вот один из них, который учитывает это, преобразовывая их в секунды:
awk -F'[m,]' '{print $1 "," $2*60 + $3}' file.csv
И несколько демо:
$ ... <(echo -e "345,0m0.047s\n345,1m0.047s\n345,1m2.047s")
345,0.047
345,60.047
345,62.047
Я не уверен, почему вы когда-либо захотите удалить десятичную точку, но вы можете передать результат через sed 's/\.//g', если вам это действительно нужно:
$ ... <(echo -e "345,0m0.047s\n345,1m0.047s\n345,1m2.047s") | sed 's/\.//g'
345,0047
345,60047
345,62047
Eugh.
И, учитывая это, выход time - что, если значение содержит часы или даже дни? Я немного поиграл и придумал этот маленький краситель:
awk -F'[dhms,]' 'BEGIN{split("1 60 3600 86400", T, " ")}{t=0; for (i=NF-1; i>1; i--) t+=T[NF-i]*$i; printf("%s,%.3f\n", $1, t)}'
Это будет обрабатывать следующие форматы: *s *m*s *h*m*s и *d*h*m*s и конвертировать их все в секундах (до трех знаков после запятой). Обязательное демонстрационное время:
$ ... <(echo -e "345,1.2s\n345,12m5s\n345,1h2m5s\n345,1d2h1m2.047s")
345,1.200
345,725.000
345,3725.000
345,93662.047
Еще один через awk,
awk -F, -v OFS="," '{gsub(/0m/,"",$2);gsub(/\./,"",$2);gsub(/s/,"",$2); print $1,$2}' file
Пример:
$ echo '345,0m0.047s' | awk -F, -v OFS="," '{gsub(/0m/,"",$2);gsub(/\./,"",$2);gsub(/s/,"",$2); print $1,$2}'
345,0047
И соответствующий,
$ echo '345,52m0.047s' | awk -F, -v OFS="," '{gsub(/^.*?m/,"",$2);gsub(/\./,"",$2);gsub(/s/,"",$2); print $1,$2}'
345,0047
Ответ @kraxor использует sed, чтобы удалить «все остальное» из строки, а затем просто показать строку.
Но - что на самом деле «все остальное»? Здесь у нас есть идея, по крайней мере, из одной строки выборки. Но что, когда мы получаем строку заголовка CSV? Что удалить? В общем, мы не знаем.
Поэтому на самом деле лучше «все остальное» !
echo '345,0m0.047s' | sed -n -r 's/^(.*),.*[^0-9]([0-9]*)\.(.*)s$/\1,\2\3/p'
345,0047
Работает до сих пор!
Ответ @kraxor использует sed, чтобы удалить «все остальное» из строки, а затем просто показать строку.
Теперь некоторые другие вход, довольно нормальный, с двумя строками данных:
ID,execution_time
123, Oops a comment0m0.0333s
345,0m0.047s
Huh ?! Похоже на другой вход, довольно нормальный , на самом деле!
echo "ID,execution_time\n123, Oops a comment0m0.0333s\n345,0m0.047s" | sed -r -n 's/^(.*),.*[^0-9]([0-9]*)\.(.*)s$/\1,\2\3/p'
123,00333
345,0047
Выглядит хорошо и правильно!
Чтобы показать, что это имеет некоторые достоинства, чтобы сделать это таким образом, я сравню с более ранним ответом:
echo "ID,execution_time\n123, Oops a comment0m0.0333s\n345,0m0.047s" | sed 's/[0-9]*m\|s\|\.//g'
ID,execution_tie
123, Oop a coent00333
345,0047
Ok , фактические, чистые линии передачи данных прошли хорошо;
(Обратите внимание, что есть решение явно пропускать строку заголовка (или, может быть, первую строку данных, мы знаем?))