在每行中搜索多个模式并将其输出到新文件中

在每行中搜索多个模式并将其输出到新文件中

这是示例文件。实际的日志比这个大得多。

user@linux:~$ cat log.txt 
[24/09/2018:22:41:49 GMT] "PROXY_SERVER_BA2" c-ip=x.x.x.x cs-bytes=1198 cs-categories="Technology/Internet" cs-host=shavar.services.mozilla.com cs-ip=y.y.y.y cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=60 rs-status=0 s-action=TCP_TUNNELED

[24/09/2018:17:45:44 GMT] "PROXY_SERVER_AA2" c-ip=x.x.x.x cs-bytes=152450 cs-categories="Business/Economy" cs-host=cvshipping.ups.com cs-ip=z.z.z.z cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=268 rs-status=0 s-action=TCP_TUNNELED

[24/09/2018:17:44:03 GMT] "PROXY_SERVER_AA2" c-ip=x.x.x.x cs-bytes=1795 cs-categories="Software Downloads" cs-host=blocklist.addons.mozilla.org cs-ip=z.z.z.z cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=61 rs-status=0 s-action=TCP_TUNNELED

[24/09/2018:17:41:44 GMT] "PROXY_SERVER_AA2" c-ip=x.x.x.x cs-bytes=3882 cs-categories="Web Ads/Analytics" cs-host=cebwa.d2.sc.omtrdc.net cs-ip=z.z.z.z cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" cs-username=johndoe dnslookup-time=0 duration=35 rs-status=0 s-action=TCP_TUNNELED

[20/09/2018:15:48:50 GMT] "PROXY_SERVER_AA2" c-ip=a.a.a.a cs-auth-group=Domain%20Users cs-bytes=227 cs-categories="Web Ads/Analytics;Suspicious" cs-host=data35.adlooxtracking.com cs-ip=b.b.b.b cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0" cs-username=johndoe duration=0 rs-status=0 s-action=TCP_TUNNELED

[20/09/2018:15:48:35 GMT] "PROXY_SERVER_AA2" c-ip=a.a.a.a cs-auth-group=Domain%20Users cs-bytes=3201 cs-categories="Search Engines/Portals" cs-host=www.google.com cs-ip=b.b.b.b cs-method=CONNECT cs-uri-path=/ cs-uri-port=443 cs-uri-scheme=tcp cs-User-Agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0" cs-username=johndoe dnslookup-time=0 duration=117 rs-status=0 s-action=TCP_TUNNELED
user@linux:~$ 

我的目标是获取每行的时间戳、类别和主机名,并将其重定向到一个新文件。

时间戳(里面[ ]

user@linux:~$ sed -n 's/^.*\[//p' log.txt | cut -d ']' -f1
24/09/2018:22:41:49 GMT
24/09/2018:17:45:44 GMT
24/09/2018:17:44:03 GMT
24/09/2018:17:41:44 GMT
20/09/2018:15:48:50 GMT
20/09/2018:15:48:35 GMT
user@linux:~$ 

主机名(后cs-host=

user@linux:~$ sed -n 's/^.*cs-host=//p' log.txt | cut -d\  -f1
shavar.services.mozilla.com
cvshipping.ups.com
blocklist.addons.mozilla.org
cebwa.d2.sc.omtrdc.net
data35.adlooxtracking.com
www.google.com
user@linux:~$ 

类别cs-categories="之间"

user@linux:~$ sed -n 's/^.*cs-categories="//p' log.txt | cut -d '"' -f1
Technology/Internet
Business/Economy
Software Downloads
Web Ads/Analytics
Web Ads/Analytics;Suspicious
Search Engines/Portals
user@linux:~$ 

是否可以运行单个命令来产生这样的输出,而不是sed逐个执行命令?

预期输出

24/09/2018:22:41:49 GMT    shavar.services.mozilla.com      Technology/Internet
24/09/2018:17:45:44 GMT    cvshipping.ups.com               Business/Economy
24/09/2018:17:44:03 GMT    blocklist.addons.mozilla.org     Software Downloads
24/09/2018:17:41:44 GMT    cebwa.d2.sc.omtrdc.net           Web Ads/Analytics
20/09/2018:15:48:50 GMT    data35.adlooxtracking.com        Web Ads/Analytics;Suspicious
20/09/2018:15:48:35 GMT    www.google.com                   Search Engines/Portals

另外,如果您对此有更好的解决方案,请告诉我。

答案1

会走多远

sed -r '/^$/d; s/^[^[]*[[]([^]]*)[]].*cs-categories="([^"]*)".*cs-host=([^ ]*) .*/\1\t\3\t\2/' file
24/09/2018:22:41:49 GMT shavar.services.mozilla.com Technology/Internet
24/09/2018:17:45:44 GMT cvshipping.ups.com  Business/Economy
24/09/2018:17:44:03 GMT blocklist.addons.mozilla.org    Software Downloads
24/09/2018:17:41:44 GMT cebwa.d2.sc.omtrdc.net  Web Ads/Analytics
20/09/2018:15:48:50 GMT data35.adlooxtracking.com   Web Ads/Analytics;Suspicious
20/09/2018:15:48:35 GMT www.google.com  Search Engines/Portals

我懂了?

sed -r '                        use extended regular expressions in the script
/^$/d                           delete empty lines

s/^[^[]*[[]([^]]*)[]].*         look for date time string between square brackets and prepare for 
                                the first "back reference"
cs-categories="([^"]*)".*       look for the string after cs-categories and prepare for second "b r"
cs-host=([^ ]*)                 look for the string after cs-host and prepare for third "b r"
.*/\1\t\3\t\2/                  create output line from back references separated by <TAB> chars.
'

答案2

使用带有前瞻功能的 perl:这样主机位于类别之前或之后并不重要

perl -lne '
    m(
        ^\[ (.*?) \]                   # match the timestamp
        (?=.* cs-categories= "(.+?)")  # look ahead for the category
        (?=.* cs-host= (\S+) )         # look ahead for the host
    )x
    and print join ",", $1,$2,$3
' log.txt 

答案3

使用 awk 怎么样:

awk '{t=""; h=""; c=""; for (i=1; i<=NF; i++) {if ($i ~ /^\[/) {t=$i} if ($i ~/^cs-host=/) {h=$i} if ($i ~ /^cs-categories=/) {c=$i}} if ((t != "") && (h != "") && (c != "")) printf("%s %s %s\n", t, h, c)}' _inputfile_

这是对您可以做什么的粗略估计。基本上它只是循环遍历给定行中的每个空白字段并检查该行是否以某个字符串开头。如果然后将该字段的值放入某个变量中。处理完所有字段后,如果所有 3 个字段都不为空,则会打印出这些字段。然后它移至输入文件中的下一行。

我没有做任何事情来处理字符串中的空格。您可以在现有检查之一中进行进一步检查,以查看字符串是否以双引号结尾。如果没有,请将下一个字段附加到变量中。

我也没有对子字符串做任何事情来摆脱诸如 [、] 和 " 之类的东西。我把它留给你作为练习。:)

相关内容