
Eingabedatei:Enthält 3 Spalten, wobei die 3. Spalte das Datum im DD-MMM-YYYY
Beispieldatenformat enthält
:
1232,abdc, 02-Jan-2014
4534,kdafh, 20-Feb-2014
364,asjhdk, 11-Jul-2012
Benötigte Ausgabe:
1232,abdc, 2014-01-02
4534,kdafh, 2014-02-20
364,asjhdk, 2012-07-11
Funktion „Datum“ wird verwendet: date -d 20-DEC-2014 +%Y-%m-%d
Bei Verwendung des Awk-Befehls tritt ein Fehler auf
. Gibt es eine andere Möglichkeit?
Antwort1
Eine mögliche Antwort mit awk, vorausgesetzt, die Eingabedatei ist input-file.txt und die Ausgabedatei ist output-file.txt:
awk -F ',' '{printf("%s,%s,",$1,$2);system("date -d "$3" +%Y-%m-%d");}' input-file.txt > output-file.txt
Antwort2
Verwenden vonMüller( mlr
), um die überzähligen Leerzeichen in der CSV-Eingabe ohne Header zu bereinigen und dann das 3. Feld neu zu schreiben. Das 3. Feld wird neu geschrieben, indem das angegebene Datum strptime()
mit der Zeitformatzeichenfolge analysiert und dann der resultierende Unix-Zeitstempel mit und der Formatierungszeichenfolge %d-%b-%Y
neu formatiert wird (Sie könnten beispielsweise anstelle von verwenden ):strftime()
%F
%Y-%m-%d
%F
mlr --csv -N \
clean-whitespace then \
put '$3 = strftime(strptime($3,"%d-%b-%Y"),"%F")' file
Angesichts der Daten in der Frage würde dies ergeben:
1232,abdc,2014-01-02
4534,kdafh,2014-02-20
364,asjhdk,2012-07-11
strptime()
Wenn Ihre Daten einen Zeitstempel im selben Feld haben, können Sie die in den - und -Aufrufen verwendeten Formatzeichenfolgen strftime()
Ihren Anforderungen entsprechend anpassen.
strftime
Was diese Formatierungszeichenfolgen bedeuten und welche Möglichkeiten Sie zum Formatieren von Datum und Uhrzeit haben, erfahren Sie im Handbuch zu Ihrem System.
Antwort3
Angenommen, Ihr eingegebener Text sieht wie folgt aus:
1232,abdc, 02-Jan-2014 18:01:37</br>
4534,kdafh, 20-Feb-2014 07:17:19</br>
364,asjhdk, 11-Jul-2012 23:20:30</br>
meine Antwort wäre:
cat input-file.txt | sed 's[</br>[[g' | awk -F ',' '{printf("%s,%s,",$1,$2);system("date -d \""$3" "$4"\" +\"%Y-%m-%d %H:%M:%S\"");}' > output-file.txt
Und wenn die Datensätze in einer einzigen Zeile stehen (keine neue Zeile in der Eingabedatei nach dem </br>), wäre es
cat input-file.txt | sed 's[</br>[\n[g' | awk -F ',' '{printf("%s,%s,",$1,$2);system("date -d \""$3" "$4"\" +\"%Y-%m-%d %H:%M:%S\"");}' > output-file.txt
Antwort4
Sie möchten keinen neuen Prozess erstellen, der für jede Zeile einer Datei eine Shell und einen weiteren Befehl ausführt. Das wäre sehr ineffizient. Wenn eine Shell Code basierend auf der Eingabe interpretiert, ist dies auch ein Rezept für die Einführung von Schwachstellen bei der Befehlsinjektion. Darüber hinaus -d
ist diese Option nicht standardmäßig.
Hier würde ich ein Textverarbeitungstool verwenden, das Zeitmanipulationen durchführen kann, wie z. B. Perl:
perl -MTime::Piece -pe '
s{\d+-\w+-\d+$}{Time::Piece->strptime($&, "%d-%b-%Y")->ymd}e
' < your-file
Dort gleichen wir das <digits>-<word-characters>-<digits>
am Ende der Zeile ( $
) gefundene Element ab, interpretieren es als <day>-<month-abbrev>-<year>
und formatieren es neu, als <yead>-<month>-<day>
würde das Time::Piece-Modul des Perl-Kerns verwendet.