강찬희*_*강찬희 5 command-line text-processing
我需要一个单行命令来编译和打印日志文件中列出的所有消耗性运载火箭名称。
ELV 名称都在/elv目录下以大写字母列出。
输出应以每行一个名称的格式出现,没有重复:
ALICE
BOB
CHARLIE
Run Code Online (Sandbox Code Playgroud)
我试过
grep "GET" NASA_access_log_Aug95.txt | grep "ELV" | wc -l
Run Code Online (Sandbox Code Playgroud)
但它只向我显示了 ELV 的数量,没有打印 ELV 名称
以下是我的日志文件示例NASA_access_log_Aug95.txt:
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:31 -0400] "GET /elv/TITAN/mars1s.jpg HTTP/1.0" 200 1156
www-a2.proxy.aol.com - - [03/Aug/1995:20:43:31 -0400] "GET /elv/DELTA/dsolids.jpg HTTP/1.0" 200 24558
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:32 -0400] "GET /elv/TITAN/mars3s.jpg HTTP/1.0" 200 1744
castor.gel.usherb.ca - - [03/Aug/1995:20:43:33 -0400] "GET /shuttle/missions/51-l/movies/ HTTP/1.0" 200 372
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:33 -0400] "GET /elv/ATLAS_CENTAUR/atc69s.jpg HTTP/1.0" 200 1659
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:35 -0400] "GET /elv/TITAN/mars2s.jpg HTTP/1.0" 200 1549
palona1.cns.hp.com - - [03/Aug/1995:20:43:36 -0400] "GET /shuttle/missions/sts-69/count69.gif HTTP/1.0" 200 46053
www-c1.proxy.aol.com - - [03/Aug/1995:20:43:38 -0400] "GET /shuttle/missions/sts-71/images/KSC-95EC-0882.gif HTTP/1.0" 200 51289
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:40 -0400] "GET /elv/ATLAS_CENTAUR/acsuns.jpg HTTP/1.0" 200 2263
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:41 -0400] "GET /elv/ATLAS_CENTAUR/goess.jpg HTTP/1.0" 200 1306
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:45 -0400] "GET /elv/DELTA/dsolidss.jpg HTTP/1.0" 200 1629
Run Code Online (Sandbox Code Playgroud)
你只需要:
awk -F'/' '/elv/ && !seen[$5]++ {print $5}' infile
Run Code Online (Sandbox Code Playgroud)
这将打印每个斜杠的第五个字段/作为字段分隔符,如果它之前没有在命名的数组中设置seen并且该行应该包含elv. 另请参阅awk '!a[$0]++' 如何工作?以及Stack Overflow 上的这个答案。
对于给定的样本,输出将是:
TITAN
DELTA
ATLAS_CENTAUR
Run Code Online (Sandbox Code Playgroud)
我只会使用grep和sort -u:
$ grep -Po '/elv/\K[^/]+' NASA_access_log_Aug95.txt | sort -u
ATLAS_CENTAUR
DELTA
TITAN
Run Code Online (Sandbox Code Playgroud)
在-P使Perl兼容的正则表达式这让我们使用\K它的意思是“忽略任何匹配了这一点。” 的-o意思是“仅示出了线的匹配部”。然后,正则表达式的意思是“查找/elv/,忽略匹配到的所有内容/elv/,然后查找一个或多个非/字符 ( [^/]+)。
你可以这样做:
grep 'elv' NASA_access_log_Aug95.txt | awk '{print $7}' | sed 's/[a-z0-9./]//g' | sort -u
Run Code Online (Sandbox Code Playgroud)
鉴于日志文件中的示例片段,这将输出:
ATLAS_CENTAUR
DELTA
TITAN
Run Code Online (Sandbox Code Playgroud)
管道命令的说明,按它们出现的顺序:
grep 'elv' NASA_access_log_Aug95.txt
将输出您包含的所有行 elv
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:31 -0400] "GET /elv/TITAN/mars1s.jpg HTTP/1.0" 200 1156
www-a2.proxy.aol.com - - [03/Aug/1995:20:43:31 -0400] "GET /elv/DELTA/dsolids.jpg HTTP/1.0" 200 24558
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:32 -0400] "GET /elv/TITAN/mars3s.jpg HTTP/1.0" 200 1744
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:33 -0400] "GET /elv/ATLAS_CENTAUR/atc69s.jpg HTTP/1.0" 200 1659
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:35 -0400] "GET /elv/TITAN/mars2s.jpg HTTP/1.0" 200 1549
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:40 -0400] "GET /elv/ATLAS_CENTAUR/acsuns.jpg HTTP/1.0" 200 2263
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:41 -0400] "GET /elv/ATLAS_CENTAUR/goess.jpg HTTP/1.0" 200 1306
cc-rd6-mg1-dip4-9.massey.ac.nz - - [03/Aug/1995:20:43:45 -0400] "GET /elv/DELTA/dsolidss.jpg HTTP/1.0" 200 1629
Run Code Online (Sandbox Code Playgroud)awk '{print $7}'
将为您提供第 7 列信息(您想要的信息)。请记住,这计算列除以空格。
/elv/TITAN/mars1s.jpg
/elv/DELTA/dsolids.jpg
/elv/TITAN/mars3s.jpg
/elv/ATLAS_CENTAUR/atc69s.jpg
/elv/TITAN/mars2s.jpg
/elv/ATLAS_CENTAUR/acsuns.jpg
/elv/ATLAS_CENTAUR/goess.jpg
/elv/DELTA/dsolidss.jpg
Run Code Online (Sandbox Code Playgroud)sed 's/[a-z0-9./]//g'
将过滤掉所有不需要的字符(即小写a-z,数字0-9,.和/)
TITAN
DELTA
TITAN
ATLAS_CENTAUR
TITAN
ATLAS_CENTAUR
ATLAS_CENTAUR
DELTA
Run Code Online (Sandbox Code Playgroud)sort -u
将防止出现重复项并按字母顺序对它们进行排序。
ATLAS_CENTAUR
DELTA
TITAN
Run Code Online (Sandbox Code Playgroud)使用 Perl,正则表达式匹配/后面的 -delimited 元素elv并将它们推送到哈希中:
$ perl -lne '$h{$1}++ if m:/elv/(.*?)/: }{ for $k (sort keys %h) {print $k}' NASA_access_log_Aug95.txt
ATLAS_CENTAUR
DELTA
TITAN
Run Code Online (Sandbox Code Playgroud)
您也可以sed在一些帮助下使用sort
$ sed -rn '\|/elv/| s|.*/elv/([^/]+).*|\1|p' NASA_access_log_Aug95.txt | sort -u
ATLAS_CENTAUR
DELTA
TITAN
Run Code Online (Sandbox Code Playgroud)
-r 使用扩展正则表达式(节省几个反斜杠)-n 不要打印我们不要求的行\|/elv/|用/elv/(\|开头的意思是用来|不/分隔地址的行)s|old|new|替换old为new.*/elv/ 之前和包括的任何字符 /elv/([^/]+) 保存所有字符直到下一个 /.* 任意数量的任意字符\1 参考我们保存的字符p 打印我们处理过的行sort -u 对输入进行排序并删除重复项