Мне просто интересно, как можно использовать awk для поиска точных совпадений.
например
$ 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
Как вы можете видеть, приведенная выше команда выводит номер индекса всех строк, содержащих строку/число «9». Есть ли способ заставить awk выводить номер индекса только в 4-й строке вывода cal выше? Может быть, есть еще более элегантное решение?
Я использую awk, чтобы получить название дня недели с помощью команды cal. Вот вся строка кода:
$ 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]}')
Проблема с приведенным выше кодом заключается в том, что если найдено несколько совпадений, то я получаю несколько результатов, тогда как я хочу, чтобы он вывел только один результат.
Спасибо!
решение1
Вы могли бы получить grep
на выходе cal
только одну строку:
$ cal 09 09 2009 | grep -E '(^9 | 9 | 9$)' | awk ...
Команда grep соответствует одному из следующих значений:
- 9 с последующим пробелом в начале строки
- Цифра 9, окруженная пробелами
- Пробел и цифра 9 в конце строки.
Как вам эта работа?
решение2
Я бы сделал это с помощью чего-то вроде
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]}}}')"
Здесь BEGIN
выполняется в начале для настройки days
массива; другой шаблон срабатывает в строках 2 и выше (пропуская заголовок), проходит по столбцам, пока не найдет day
, а затем использует номер столбца для поиска дня недели. $
in awk
— оператор ссылки на поле; как и $1
первое поле, $n
— поле, пронумерованное значением n
. Я также передаю $day из оболочки в скрипт с назначением в начале строки awk
. NR
— номер записи (номер строки); NF
— количество полей в строке. (Вы можете задать RS
и FS
, соответственно, чтобы изменить то, что разделяет записи и поля соответственно.)
(Обратная косая черта и новая строка после вертикальной черты |
нужны только для ясности и чтобы не прокручивать страницу)слишкоммного.)
На этот раз это проверено.
решение3
скрипт на этой странице делает именно это
http://www.computing.net/answers/unix/find-the-day-of-week-using-awk/5243.html
решение4
Попробуйте это:
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)
}'
Все в одной строке:
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) }'
Демонстрация:
$ 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
Вот усовершенствованный сценарий, на который дал ссылку Мохамед:
cal 09 2009 | awk -v "d=9" 'NR==2 {split($0, dow)} NR == 3 {print $0, d, dow[7 - ($NF + 35 - d) % 7]}'
Нет необходимости в head
, tail
или в куче if
заявлений.