usando awk para hacer coincidencias exactas

usando awk para hacer coincidencias exactas

Sólo me pregunto cómo podemos usar awk para hacer coincidencias exactas.

por ejemplo

$ 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

Como puede ver, el comando anterior genera el número de índice de todas las líneas que contienen la cadena/número "9", ¿hay alguna manera de hacer que awk genere el número de índice solo en la cuarta línea de la salida cal anterior? ¿Puede ser una solución aún más elegante?

Estoy usando awk para obtener el nombre del día usando el comando cal. Aquí está toda la línea de código:

     $ 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]}')

El problema con el código anterior es que si se encuentran varias coincidencias, obtengo varios resultados, mientras que quiero que genere solo un resultado.

¡Gracias!

Respuesta1

Podrías grepobtener el resultado de calsolo una línea:

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

El grep coincide con uno de:

  • Un 9 seguido de un espacio al inicio de la línea.
  • Un 9 rodeado de espacios
  • Un espacio seguido de un 9 al final de la línea.

¿Qué te parece?

Respuesta2

Haría esto con algo como

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]}}}')"

Aquí, BEGINse ejecuta al inicio para configurar la daysmatriz; el otro patrón se activa en las líneas 2 en adelante (omitiendo el encabezado), recorre las columnas hasta que encuentra dayy luego usa el número de columna para buscar el día de la semana. $in awkes el operador de referencia del campo; Así como $1es el primer campo, $nel campo está numerado por el valor de n. También estoy pasando $day desde el shell al script con la asignación al comienzo de la awklínea. NRes el número de registro (número de línea); NFes el número de campos en la línea. (Puede configurar RSy FS, respectivamente, para cambiar lo que separa los registros y los campos, respectivamente).

(La barra invertida-nuevas líneas y la nueva línea después de la tubería |son solo para mayor claridad y para que no se desplacetambiénmucho.)

Esta vez está probado.

Respuesta3

Respuesta4

Prueba esto:

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)
    }'

Todo en una sola línea:

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) }'

Manifestación:

$ 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

Aquí hay una mejora del guión al que se vinculó Mohamed:

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

No hay necesidad de head, tailni de un montón de ifdeclaraciones.

información relacionada