Verwenden von awk zum Erstellen exakter Übereinstimmungen

Verwenden von awk zum Erstellen exakter Übereinstimmungen

ich frage mich nur, wie wir awk verwenden können, um exakte Übereinstimmungen zu erzielen.

für zB

$ cal 09 09 2009
   September 2009
Su Mo Tu We Th Fr Sa
   1  2  3  4  5
6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30



$ cal 09 09 2009 | awk '{day="9"; col=index($0,day); print col }'
17
0
0
11
20
0
8
0

Wie Sie sehen, gibt der obige Befehl die Indexnummer aller Zeilen aus, die die Zeichenfolge/Zahl „9“ enthalten. Gibt es eine Möglichkeit, dafür zu sorgen, dass awk die Indexnummer nur in der vierten Zeile der obigen Cal-Ausgabe ausgibt??? Ist das vielleicht eine noch elegantere Lösung?

Ich verwende awk, um den Tagesnamen mit dem Befehl „cal“ abzurufen. Hier ist die gesamte Codezeile:

     $ dayOfWeek=$(cal $day $month $year | awk '{day='$day'; split("Sunday Monday Tuesday Wednesday Thursday Friday Saturday", array); column=index($o,day); dow=int((column+2)/3); print array[dow]}')

Das Problem mit dem obigen Code besteht darin, dass ich mehrere Ergebnisse erhalte, wenn mehrere Übereinstimmungen gefunden werden, obwohl ich nur ein Ergebnis ausgeben möchte.

Danke!

Antwort1

Sie könnten grepdie Ausgabe so gestalten cal, dass sie nur die folgende Zeile enthält:

$ cal 09 09 2009 | grep -E '(^9 | 9 | 9$)' | awk ...

Das Grep-Tool findet eines der folgenden Ergebnisse:

  • Eine 9 gefolgt von einem Leerzeichen am Zeilenanfang
  • Eine 9 umgeben von Leerzeichen
  • Ein Leerzeichen gefolgt von einer 9 am Ende der Zeile.

Wie funktioniert das für Sie?

Antwort2

Ich würde das mit so etwas machen wie

dayOfWeek="$(cal $month $year |
             awk -v day=$day \
                'BEGIN {split("Sunday Monday Tuesday Wednesday Thursday Friday Saturday", days)}
                 NR > 2 {for (i = 1; i <= NF; i++) {if ($i == day) {print days[i]}}}')"

Hier BEGINwird am Anfang ausgeführt, um das Array einzurichten days; das andere Muster wird ab Zeile 2 ausgelöst (überspringt die Kopfzeile), durchläuft die Spalten, bis es findet day, und verwendet dann die Spaltennummer, um den Wochentag nachzuschlagen. $in awkist der Feldreferenzoperator; ebenso wie $1das erste Feld ist, $nist das Feld, das durch den Wert von nummeriert wird n. Ich übergebe auch $day von der Shell an das Skript mit der Zuweisung am Anfang der awkZeile. NRist die Datensatznummer (Zeilennummer); NFist die Anzahl der Felder in der Zeile. (Sie können RSbzw. festlegen FS, um zu ändern, was Datensätze bzw. Felder trennt.)

(Der Backslash-Newline und der Newline nach dem Pipe-Zeichen |dienen nur der Übersichtlichkeit und verhindern, dass es scrollt.zuviel.)

Diesmal wird es getestet.

Antwort3

Antwort4

Probieren Sie Folgendes aus:

cal 09 2009 | awk -v "num=9" '
    BEGIN {
        OFS="\t";
        day=" ?[^0-9]" num "([^0-9]|$)"
    }
    NR==2 {dow = $0}
    $0 ~ day {
        col=match(" " $0, day);
        print $0, col, substr(dow,col,2)
    }'

Alles in einer Zeile:

cal 09 2009 | awk -v "num=9" 'BEGIN {OFS="\t"; day=" ?[^0-9]" num "([^0-9]|$)"} NR==2 {dow = $0} $0 ~ day {col=match(" " $0, day); print $0, col, substr(dow,col,2) }'

Demo:

$ for i in {1..30}; do cal 09 2009 | awk -v "num=$i" 'BEGIN {OFS="\t"; day=" ?[^0-9]" num "([^0-9]|$)"} NR==2 {dow = $0} $0 ~ day {col=match(" " $0, day); print $0, num, col, substr(dow,col,2) }'; done
       1  2  3  4  5    1       7       Tu
       1  2  3  4  5    2       10      We
       1  2  3  4  5    3       13      Th
       1  2  3  4  5    4       16      Fr
       1  2  3  4  5    5       19      Sa
 6  7  8  9 10 11 12    6       1       Su
 6  7  8  9 10 11 12    7       4       Mo
 6  7  8  9 10 11 12    8       7       Tu
 6  7  8  9 10 11 12    9       10      We
 6  7  8  9 10 11 12    10      13      Th
 6  7  8  9 10 11 12    11      16      Fr
 6  7  8  9 10 11 12    12      19      Sa
13 14 15 16 17 18 19    14      4       Mo
13 14 15 16 17 18 19    15      7       Tu
13 14 15 16 17 18 19    16      10      We
13 14 15 16 17 18 19    17      13      Th
13 14 15 16 17 18 19    18      16      Fr
13 14 15 16 17 18 19    19      19      Sa
20 21 22 23 24 25 26    21      4       Mo
20 21 22 23 24 25 26    22      7       Tu
20 21 22 23 24 25 26    23      10      We
20 21 22 23 24 25 26    24      13      Th
20 21 22 23 24 25 26    25      16      Fr
20 21 22 23 24 25 26    26      19      Sa
27 28 29 30             28      4       Mo
27 28 29 30             29      7       Tu
27 28 29 30             30      10      We

Hier ist eine Verbesserung des Skripts, auf das Mohamed verlinkt hat:

cal 09 2009 | awk -v "d=9" 'NR==2 {split($0, dow)} NR == 3 {print $0, d, dow[7 - ($NF + 35 - d) % 7]}'

Es besteht keine Notwendigkeit für headoder taileine Reihe von ifAnweisungen.

verwandte Informationen