Bash-Skript / awk zum Eingeben und Ausgeben einer CSV-Datei

Sep 28 2020

Ich habe Probleme beim Erstellen eines bash / awk / sed-Skripts, das eine durch Kommas getrennte CSV-Datei mit drei Spalten (Vorname, Nachname, Geburtsdatum) verwendet und eine andere CSV-Datei mit denselben Spalten aus der Eingabe mit einem ausgibt Zusätzliche Spalte, die die Differenz zwischen dem aktuellen Datum und dem Geburtsdatum in Jahren anzeigt.

$ yourscript <input CSV file> <output CSV file>

input.csv könnte folgendermaßen aussehen:

bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

output.csv sollte folgendermaßen aussehen:

bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48

Antworten

3 Cbhihe Sep 28 2020 at 14:46
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

So geben Sie eine Datei mit dem Namen aus output-fileund zeigen sie gleichzeitig STDOUT an:

$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data | tee output-file
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48

Oder um einfach in dieselbe Datei auszugeben:

$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
2 Cbhihe Sep 30 2020 at 18:04

Um genauere Zeitberechnungen durchführen, können Sie gawk‚s Zeit und String - Funktionen (pro @ AdminBee Vorschlag). Eingabedaten verwenden als:

$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972

Sie können einen Zeitunterschied in Tagen zwischen jetzt und dem in jeder Zeile angezeigten Datum ermitteln, mit:

$ awk -F, 'BEGIN{today=systime()} 
           {print $0 "," int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))}' \
           data | tee output-file

 bob,wag,06/13/1958,22755
 ashley,hay,01/23/1983,13765
 evan,bert,09/11/1972,17551

Das Snippet:

int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))

führt drei grundlegende Dinge für jede Zeile der Eingabedatei aus:

  • Es berechnet die seit 1970-01-01 00:00:00 UTC (auf POSIX-Systemen) verstrichene Zeit (in Sekunden) ohne Schaltsekunden mit mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00)
  • Es berechnet die Zeitdifferenz zwischen der oben genannten Menge und der Variablen today, die die Anzahl der Sekunden enthält, die zum Zeitpunkt der Ausführung seit 1970-01-01 00:00:00 UTC vergangen sind.
  • Es dividiert den Zeitunterschied in Sekunden durch 3600 * 24, um den gleichen Wert in Tagen zu erhalten, und berücksichtigt nur den ganzzahligen Teil des Ergebnisses, um ganze Tage mit zu erhalten int().

Sie könnten damit spielen, um Ihren Zeitunterschied in Sekunden, Minuten, Stunden pro Bedarf zu ermitteln. HTH

MaheshK. Sep 28 2020 at 11:49

Um den Datumsunterschied zu ermitteln, können Sie diese kleine Bash-Funktion verwenden

Verwenden Sie die folgenden Nummern für Ihre Anforderungen

  • #Um Tage Unterschied zu erhalten: 86400
  • #Um Jahre Unterschied zu bekommen: 31536000

Bash-Funktion

datediff() {
  current_date=$(date -d "$1" +%s)
  birth_date=$(date -d "$2" +%s)
  echo $(( (current_date - birth_date) / 31536000)) Years
}

Verwendung:

datediff '9/28/2020' '1/1/1999'

Ausgabe:

 21 years
MarcinŚlusarz Jan 09 2021 at 09:58

Je nachdem, was Sie wirklich wollen:

Jahre Unterschied:

(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite \
 "select *, strftime('%Y', 'now') - substr(d, 7, 4) as year_diff
  from input" | csv-header --remove

Alter:

(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite
  "select *, strftime('%Y', 'now') - substr(d, 7, 4) -
             case when strftime('%m%d', 'now') >= (substr(d, 1, 2) || substr(d, 4, 2))
             then 0 else 1 end as age
  from input" | csv-header --remove

csv-sqlite und csv-header stammen von csv-nix-tools