awk -F/命令含义解析及日志处理脚本中的作用疑问
问题详情
我正在完成一项作业,要求找出目录下所有全大写的文件/目录名,去重后保存到txt文件中。给定的网站访问日志示例如下:
website.com - - [date/date/date:date:date:date -0400] "GET /elv/HELLO/wave.gif HTTP/1.0" 200 1318 website.com - - [date/date/date:date:date:date -0400] "GET /elv/ball.gif HTTP/1.0" 200 306
我尝试了以下脚本:
grep "/elv/" filename.txt | awk '{print $7}' | awk -F/ '{print $3}' | grep ^[A-Z] | sort -u > elv.txt
我已经理解了grep "/elv/" filename.txt、awk '{print $7}'、grep ^[A-Z]和sort -u > elv.txt的作用,但不明白awk -F/ '{print $3}'的必要性。我原本以为它是用来截取/elv/CAPITALISED_WORD中CAPITALISED_WORD之后的内容?
执行第一个脚本后,得到的结果是txt文件中包含/elv/下所有全大写的名称:
HELLO (list of other capitalised words)
但当我去掉awk -F/ '{print $3}'执行以下脚本时:
grep "/elv/" filename.txt | awk '{print $7}' | grep ^[A-Z] | sort -u > elv.txt
结果文件为空。我原本以为第一个脚本会得到类似HELLO/wave.gif的结果,对此感到困惑。
解答
1. awk -F/ '{print $3}'的作用
-F/是指定awk的字段分隔符为/,当awk '{print $7}'提取出/elv/HELLO/wave.gif或/elv/ball.gif这类路径字符串时,用/分割后,字段会被拆分为:
- 第1字段:空字符串(路径以
/开头,第一个分隔符前无内容) - 第2字段:
elv - 第3字段:
HELLO(或ball) - 第4字段:
wave.gif(或ball.gif)
print $3就是提取/elv/后面紧跟的一级目录名,也就是你需要检查是否全大写的目标内容。
2. 去掉该命令后结果为空的原因
去掉awk -F/ '{print $3}'后,grep ^[A-Z]会匹配以大写字母开头的整行内容,但此时传入grep的是/elv/HELLO/wave.gif这类路径——路径以/开头,并非大写字母,自然匹配不到任何内容,所以结果文件为空。
3. 关于预期的HELLO/wave.gif结果
第一个脚本因为用了awk -F/ '{print $3}',已经把HELLO单独提取出来,所以不会得到HELLO/wave.gif。如果要保留这类完整路径并筛选其中目录名全大写的,需要调整匹配逻辑,但当前脚本的逻辑符合作业目标:准确提取/elv/下的一级目录名并筛选全大写的内容。
内容的提问来源于stack exchange,提问作者Ariel

