我只是想知道如何使用 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 仅在上面的 cal 输出的第 4 行中输出索引号。??? 可能是一个更优雅的解决方案?
我正在使用 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
,然后使用列号查找星期几。 $
inawk
是字段引用运算符;就像$1
是第一个字段一样,$n
是按值编号的字段n
。我还将在行首赋值将 $day 从 shell 传递给脚本awk
。 NR
是记录号(行号);NF
是该行上的字段数。(您可以分别设置RS
和FS
来分别更改记录和字段的分隔符。)
(反斜杠换行符和管道后的换行符|
只是为了清晰起见,并使其不滚动也很多。)
这次经过测试。
答案3
答案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
以下是 Mohamed 所链接脚本的改进版:
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
语句。