Rufen Sie das Datum innerhalb eines awk-Befehls auf, um die Ausgabe zu formatieren

8

Ich habe eine csvDatei im folgenden Format:

20171129,1
20171201,0.5
20171201,0.5
20171202,1.25
20171202,1.75

Ich benutze den folgenden Befehl, um das zweite Feld zusammenzufassen, wenn es mit diesem Befehl dem gleichen Datum folgt:

awk -F ',' '{a[$1] += $2} END{for (i in a) print "On " i, "you spend: "a[i] " hour(s)"}' << "file.csv"

Die Ausgabe, die ich bekomme, sieht folgendermaßen aus:

On 20171129 you spend: 1 hour(s)
On 20171201 you spend: 1 hour(s)
On 20171202 you spend: 3 hour(s)

Was ich jetzt erreichen möchte, ist das Format so zu formatieren, als würde ich mit:

awk -F ',' '{a[$1]} END{for (i in a) print i}' << "file.csv" \
 | date +"%a, %d.%m.%Y" -f -

# prints:
Wed, 29.11.2017
Fri, 01.12.2017
Sat, 02.12.2017

Mein Endergebnis würde also so aussehen:

On Wed, 29.11.2017 you spend: 1 hour(s)
On Fri, 01.12.2017 you spend: 1 hour(s)
On Sat, 02.12.2017 you spend: 3 hour(s)

Ist es möglich, dateinnerhalb des awkBefehls aufzurufen, um die Ausgabe zu formatieren?

nath
quelle
Was ist Mi? Minday?
David Conrad
@DavidConrad Miist Deutsch für Mittwoch= Wednesday, dachte , dies nicht zu viel von einer Sache war, aber du hast recht, ich sollte das Snippet bearbeiten: Wed, Fri, Sat, mehr Sinn auf Englisch QA Board gemacht :-)
Nath
Oh, das ist okay. Ich dachte, es wäre vielleicht ein Tippfehler für Mo (Montag) gewesen, war mir aber nicht sicher. Es tut uns leid.
David Conrad
@ DavidConrad Alles gut! Danke, dass du darauf hingewiesen hast!
nath

Antworten:

16

Sie können gawk mit den Funktionen strftime und mktime verwenden ( https://www.gnu.org/software/gawk/manual/html_node/Time-Functions.html ).

gawk -F ',' '{a[$1] += $2} END{for (i in a) print "On " strftime("%a, %d.%m.%Y", mktime( substr(i,1,4) " " substr(i,5,2) " " substr(i,7,2) " 0 0 0" )) " you spend: "a[i] " hour(s)" }' files.csv

In weiteren Details:

gawk -F ',' '
  {
    a[$1] += $2
  }
  END{
    for (i in a) {

      # mktime needs a date formated like this "2017 12 31 23 59 59"
      # strftime needs a Unix timestamp (produced by mktime)

      print "On " strftime("%a, %d.%m.%Y", mktime( substr(i,1,4) " " substr(i,5,2) " " substr(i,7,2) " 0 0 0" )) " you spend: "a[i] " hour(s)"

    }
  }' files.csv

Mit einem einfachen awk müssen Sie den Befehl aufrufen und sein Ergebnis mit getline lesen :

awk -F ',' '{a[$1] += $2} END{ for (i in a) { COMMAND = "date +\"%a, %d.%m.%Y\" -d " i ; if ( ( COMMAND | getline DATE ) 0 ) { print "On " DATE " you spend: "a[i] " hour(s)" } ; close(COMMAND) } }' files.csv

In weiteren Details:

awk -F ',' '
  {
    a[$1] += $2
  }
  END{
    for (i in a) {

      # Define command to call

      COMMAND = "date +\"%a, %d.%m.%Y\" -d " i

      # Call command and check that it prints something
      # We put the 1st line of text displayed by the command in DATE

      if ( ( COMMAND | getline DATE ) > 0 ) {
        # Print the result
        print "On " DATE " you spend: "a[i] " hour(s)"
      }

      # Close the command (important!)
      # Your child process is still here if you do not close it

      close(COMMAND)
    }
  }' files.csv 

quelle