Добавление ведущих нулей в дату и время

{ a && b && c; } >capture_file 2>&1

Обратите внимание на порядок перенаправления: сначала вы должны перенаправить stdout.

3
01.03.2018, 15:47
4 ответа

Una gran herramienta para el procesamiento de texto es awk . El siguiente ejemplo utiliza awk estándar simple en FreeBSD 11.1. @RomanPerekhrest tiene una solución elegante en otra respuesta si prefiere GNU awk.

Su entrada está separada por comas -. Por eso invocamos awkcon el parámetro -F,.

Luego podemos imprimir columnas usando la declaración print. $1es la primera columna. $2es la segunda columna.

$ awk -F, '{ print $8 }' inputfile.csv
2017-1-5 1:07:09
2017-11-25 19:57:17

Esto nos da la octava columna para cada fila.

Este es entonces el campo de fecha que desea manipular. En lugar de configurar el delimitador usando el parámetro de línea de comando -, podemos hacerlo como parte del script. FS para el delimitador de entrada y OFS para el delimitador de salida.

$ awk 'BEGIN { FS = "," } ; { print $8 }' inputfile.csv
2017-1-5 1:07:09
2017-11-25 19:57:17

Cuando trabajo con fechas, a menudo prefiero usar la utilidad datepara asegurarme de manejarlas correctamente. Y no necesito preocuparme si estoy usando GNU awk o regular. Además, obtengo una gran falla si la fecha no se analiza correctamente.

Los parámetros interesantes son:

-j     Specify we do not want to set the date at all
-f     The format string we use for input
+      The format string we use for output

Entonces, si ejecutamos esto para una fecha:

$ date -j -f "%Y-%m-%d %H:%M:%S" +"%Y-%m-%d %H:%M:%S" "2017-1-5 1:07:09"
2017-01-05 01:07:09

Entonces podemos combinar esto con awk. Observe cómo se escapan las comillas. Este es probablemente el mayor obstáculo para un principiante.

$ awk -F, '{ system("date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$8"\"")}' inputfile.csv
2017-01-05 01:07:09
2017-11-25 19:57:17

La llamada al sistema parece correcta -pero, lamentablemente, solo nos permite capturar el código de retorno y se imprime directamente en la salida. Para evitar esto usamos el patrón cmd | getline. El siguiente ejemplo simple leerá la fecha actual en mydate:

$ awk 'BEGIN { cmd = "date"; cmd | getline mydate; close(cmd); print mydate }'
Thu Mar  1 16:26:15 CET 2018

Usamos la palabra clave BEGINya que no tenemos información para este ejemplo simple.

Así que ampliemos esto:

awk 'BEGIN { FS=","; OFS=FS };
     { 
         cmd = "date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$8"\"";
         cmd | getline firstdate;
         close(cmd);
         cmd = "date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$9"\"";
         cmd | getline seconddate;
         close(cmd);
         print $1,$2,$3,$4,$5,$6,$7,firstdate,seconddate
     }' inputfile.csv

Y podemos reducirlo a una -línea:

awk 'BEGIN {FS=",";OFS=FS};{cmd="date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$8"\"";cmd | getline firstdate;close(cmd);cmd="date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$9"\"";cmd | getline seconddate;close(cmd);print $1,$2,$3,$4,$5,$6,$7,firstdate,seconddate}' inputfile.csv

Lo que me da la salida:

1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

Apéndice

Como el propósito aquí es aprender un buen hábito, mejor actualizo esta respuesta. Es un mal hábito repetir código.Cuando comience a hacer eso, debe dividir las cosas en una función. Como notará, el código a continuación se vuelve inmediatamente más legible.

awk 'function convertdate(the_date) {
         cmd = "date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""the_date"\"";
         cmd | getline formatted_date;
         close(cmd);
         return formatted_date
     }
     BEGIN { FS=","; OFS=FS };
     { 
         print $1,$2,$3,$4,$5,$6,$7,convertdate($8),convertdate($9)
     }' inputfile.csv

Acostúmbrate a esto y notarás cuánto más fácil será introducir el manejo de errores más adelante.

8
27.01.2020, 21:07

Solución sencilla de GNUawk:

awk 'BEGIN{ FS=OFS="," }{ gsub(/\<[0-9]\>/, "0&", $8); gsub(/\<[0-9]\>/, "0&", $9) }1' file
  • gsub(/\<[0-9]\>/, "0&", <field>)-reemplazar/complementar solo dígitos individuales independientes dentro de fecha y hora cadena :
    • \<y\>-son ​​límites de palabras
    • &-representa la subcadena precisa que coincidió con el patrón de expresión regular

La salida:

1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54
5
27.01.2020, 21:07
sed -r 's/([-: ])([0-9]\b)/\10\2/g' input.txt

Reemplaza todos los dígitos solos, que van precedidos por [-: ]caracteres y seguidos por cualquier carácter que no sea -palabra.

Esta solución es corta y simple, pero propensa a errores, porque no verifica el patrón de fecha y solo agrega el cero inicial a todos los dígitos solos, lo que se ajusta al patrón [-: ][0-9]\b(\b-coincide con un límite de palabra ). Pero como variante.

Entrada

1111,2222,3333,4444,5555,6666,7777,2017-1-5 1:07:09,2017-1-5 1:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

Salida

1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54
1
27.01.2020, 21:07

El paquete dateutils tiene códigos para manejar los detalles de los datos con formato de hora/fecha.

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }

pl " Input data file $FILE:"
head $FILE

pl " Expected output:"
cat $E

pl " Results, to standard format:"
dateutils.dconv -S <$FILE

pl " Results, to standard format, omitting the \"T\":"
dateutils.dconv -S -f '%F %T' <$FILE

producir:

-----
 Input data file data1:
1111,2222,3333,4444,5555,6666,7777,2017-1-5 1:07:09,2017-1-5 1:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

-----
 Expected output:
1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

-----
 Results, to standard format:
1111,2222,3333,4444,5555,6666,7777,2017-01-05T01:07:09,2017-01-05T01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25T19:57:17,2017-11-25T19:58:54

-----
 Results, to standard format, omitting the "T":
1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

En un sistema como:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30
dateutils.dconv dconv 0.3.1

Algunos detalles para dconv:

dateutils.dconv Convert DATE/TIMEs between calendrical systems. (man)
Path    : /usr/bin/dateutils.dconv
Package : dateutils
Home    : http://www.fresse.org/dateutils
Version : 0.3.1
Type    : ELF 64-bit LSB shared object, x86-64, version 1 (...)
Help    : probably available with -h,--help
Home    : https://github.com/hroptatyr/dateutils (doc)

Mis mejores deseos...salud, drl

0
27.01.2020, 21:07

Теги

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