У меня есть файл входных данных как это с именами столбцов, не включенными в файл данных (Date
, Desc
, Timestamp1
, Timestamp2
):
2016-01-01, AAA, 330, 1430
2016-01-02, ABA, 130, 930
Я должен произвести как это:
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
Как это может быть сделано?
Это могло быть сделано с заменой простой строки как ниже использования awk
, но остерегайтесь, тот этот метод, вероятно, не слишком надежен, если Ваши изменения формата немного или входные данные не допустимы.
awk -F, '/,/{printf "%s, %s, %s %02d:%02d, %s %02d:%02d\n",$1,$2,$1,int($3/100),$3%100,$1,int($4/100),$4%100}' YOUR_FILE.CSV
Или с awk
код отформатировал для лучшей удобочитаемости:
/,/ {
printf "%s, %s, %s %02d:%02d, %s %02d:%02d\n",
$1, $2,
$1, int($3 / 100), $3 % 100,
$1, int($4 / 100), $4 % 100
}
Без обиняков это работает на каждой строке, которая содержит запятую (чтобы не обрабатывать пустые строки) и просто распечатывает соответствующие значения столбцов (вход является запятой, разделенной из-за -F,
) с указанным форматом:
Результат на Ваших рассматриваемых входных данных был бы
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
Можно использовать awk
достигнуть желаемого вывода. Я не уверен, на самом деле ли пустые строки между вводом и выводом там или просто проблема форматирования, но я рассмотрел их в команде.
awk -F, '{if (NF) { print $1 "," $2 ", " $1 " " sprintf("%02d", int($3 / 100)) ":" $3 % 100 ", " $1 " " sprintf("%02d", int($4 / 100)) ":" $4 % 100 } else { print }}' < input.txt > output.txt
То, что это делает, следующие:
-F,
устанавливает разделитель поля ввода awk
кому: ,
таким образом, вход разделяется правильно.if (NF)
проверки, если количество полей ввода больше, чем нуль. Это для обработки пустых строк. Если строка пуста else
часть в конце команды распечатает пустую строку.print
управляйте печатает указанные поля: $1
первое поле от входа, даты","
печатает литеральную запятую$2
второе поле, описание", "
печатает следующую запятую$1
печатает дату снова Вашей метки времени" "
добавляет пространство между датой и временемsprintf("%02d", int($3 / 100))
сначала вычисляет часть часа времени путем деления времени на 100, отбрасывания десятичных чисел (int()
делает это), и печатает то число с начальными нулями с двумя цифрами (%02d%
как строка формата для sprintf()
дескрипторы это)":"
снова просто литеральное двоеточие$3 % 100
операция по модулю, дающая остаток от подразделения времени 100 и поэтому минуты", " $1 " " sprintf("%02d", int($4 / 100)) ":" $4 % 100
то же для второй метки времениelse
часть объяснена выше с if
.< input.txt
говорит оболочке читать awk
s вход из указанного файла.> output.txt
говорит оболочке писать awk
s вывод в тот файл.Вот вариант жемчуга (чей s/pattern/replacement/
имеет e
модификатор, который позволяет оценку выражения в замене):
perl -F', ' -lpe '$_ = join ",", @F[0,1], map {
s/(\d?\d)(\d\d)/sprintf "%s %02d:%02d", $F[0], $1, $2/e ; $_
} @F[2,3] if @F
' file
2016-01-01, AAA, 2016-01-01 03:30, 2016-01-01 14:30
2016-01-02, ABA, 2016-01-02 01:30, 2016-01-02 09:30
Следующая версия Perl с get-the-basic-elements и переформатировала - их стратегия
perl -ne '/((.*?),.*?, )(\d*)(\d\d), (\d*)(\d\d)/ and
printf("%s%s %02d:%s, %s %02d:%s\n", $1,$2,$3,$4,$2,$5,$6)'