使用sed或脚本解析,重新格式化日志文件?

时间:2015-10-16 16:52:44

标签: regex linux bash ubuntu sed

我有一个案例,我需要post-process的文件。样本格式如下: -

bigspeedpro.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
1.1.1.1 Intel::DOMAIN   from http://abcd.com/bl/BOOT via intel.criticalstack.com     F

预期输出为: -

1.1.1.1 abcd

解析如下: -

  • 任何不以IP地址开头的内容都会删除该行
  • 如果以IP地址开头,请执行

    • 删除Intel :: DOMAIN
    • from F之间根据以下字符串出现次数替换它
    • 例如malc0de或abcd

我想使用,sed但我不知道如果sed可用于匹配多个字符串,例如malc0de或abc,或许我需要一个更完整的脚本,然后只需一行存储字符串值阵列。任何的想法?顺便说一句,使用sed的例子最受欢迎。

到目前为止

  • 我知道在sed中使用d我可以删除该行并将输出重定向到文件
  • 我知道如何匹配非IP地址的正则表达式[^ a-zA-Z]
  • 我根据多项选择或字符串进行更换
\#!/bin/bash          
sed -i s/\[a-zA-Z]\/d test ./infile > testme.txt
sed -i s/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/s+\Intel::DOMAIN\\s*from(.*?)\s+F\1malc0de

或者我想保存像ARRAY =(malc0de abcd)

然后代替捕获组我可以做$ {ARRAY [2]}它会起作用吗?或者我可以做一些像 fromF之间的.net子串匹配一样的东西我复制结果字符串变量。然后搜索我的字符串,例如malc0de,如果找到替换匹配结果的搜索模式?但我不知道bash ......

更新 使用awk脚本我很干净

1.1.1.1 www.abc.com
1.1.2.2 def.com
2.2.2.2 mnx.dbc.net

但是,我希望将ip地址后的第二列缩短为我自己选择的字符串,例如在第二列中我只接受

  

ABC   高清   MNX

一旦发现它只是将整个字符串替换为

1.1.1.1 abc
1.1.2.2 def
2.2.2.2 mnx

感谢。

2 个答案:

答案 0 :(得分:5)

您提到sed解决方案是最受欢迎的,但我相信awk最容易用于您的特定任务。这是我的解决方案:

awk '/^[[:digit:]]\.[[:digit:]]\.[[:digit:]]\.[[:digit:]]/ { printf $1; gsub (/http\:\/\//," "); gsub(/\.com/," ");printf " "$4"\n"  }' inputFile.txt

这个想法很简单:默认情况下awk的字段分隔符是空格并允许打印特定字段,因此首先我们匹配以ip地址开头的行(四个数字点交替模式);我们打印第一个字段,然后删除https.com部分,域名是唯一剩下的,因此变为归档4,我们接下来打印。其余未指定打印,因此被忽略。

如果您想要编辑原始文件,awk有一个怪癖,因为它无法进行内嵌编辑,除非gawk(GNU awk),所以使用用于此目的的临时文件。

演示:

我的输入文件

xieerqi:$ cat inputFile.txt                                               
bigspeedpro.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
1.1.1.1 Intel::DOMAIN   from http://abcd.com/bl/BOOT via intel.criticalstack.com     F

whatever.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
2.2.2.2 Intel::DOMAIN   from http://asdf.com/bl/BOOT via intel.criticalstack.com     F

带临时文件传输的命令(注意我的inputFile.txt在我的主目录中,相应地调整该部分)。注意:为了以防万一,始终始终备份原始文件!或者在&&之前运行命令的第一部分,检查临时文件,如果愿意,可以将文件保存到原始文件中。

awk '/^[[:digit:]]\.[[:digit:]]\.[[:digit:]]\.[[:digit:]]/ { printf $1; gsub (/http\:\/\//," "); gsub(/\.com/," ");printf " "$4"\n"  }' inputFile.txt > /tmp/temp.txt && cat /tmp/temp.txt > $HOME/inputFile.txt
命令运行后

输出:

xieerqi:$ awk '/^[[:digit:]]\.[[:digit:]]\.[[:digit:]]\.[[:digit:]]/ { printf $1; gsub (/http\:\/\//," "); gsub(/\.com/," ");printf " "$4"\n"  }' inputFile.txt > /tmp/temp.txt && cat /tmp/temp.txt > $HOME/inputFile.txt


xieerqi:$ cat inputFile.txt                                                                                                                           
1.1.1.1 abcd
2.2.2.2 asdf

通过脚本简化

上述命令可以放入包含以下内容的脚本中:

#!/usr/bin/awk -f

/^[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*/ { 
printf $1; 

gsub (/http\:\/\//," "); 
gsub (/https\:\/\//," "); 
gsub(/\.com/," ");
printf " "$4"\n";
}

请注意,在脚本中我已经考虑了ip地址中多位数的可能性以及地址中https的可能性。

请记住使用chmod 755 /path/to/script

制作可执行脚本

这是演示:

xieerqi:$ chmod 755 ipanddomain.awk                                                                                                                   

xieerqi:$ cat inputFile.txt                                                                                                                           
bigspeedpro.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
1.1.1.1 Intel::DOMAIN   from http://abcd.com/bl/BOOT via intel.criticalstack.com     F

whatever.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
192.168.0.2 Intel::DOMAIN   from https://asdf.foobar.whatever.com/bl/BOOT via intel.criticalstack.com     F

xieerqi:$ ./ipanddomain.awk inputFile.txt                                                                                                             
1.1.1.1 abcd
192.168.0.2 asdf.foobar.whatever

要编辑原始文件,请使用重定向到临时文件的技巧,然后再回到我之前向您展示的原始文件

编辑#2

所以您已经问过:可以简单地匹配您已经知道的部分域名。我已经编辑了一下我的脚本。基本上,这个版本在$ 4字段中查找模式,如果找到它,它就会变好,那个字符串中有abcd,所以我只打印那个"

#!/usr/bin/gawk -f

/^[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*/ { 
printf $1" ";
matchDomain($4);
}

function matchDomain(str){

if (str~/foobar/)
 printf "foobar\n";
if(str~/abcd/)
 printf "abcd\n"

}

答案 1 :(得分:2)

试试这个小家伙:

Given a string s, partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.

想法是使用分组sed -nE 's/(^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}) .* [htpsw:\/.]{4,8}([0-9a-z.]+)\.com.*$/\1 \2/p' > newfile ,定义正确的群组,而不是仅使用()等替换匹配的行。\1 \2组合用于仅显示已替换的行并替换行只有匹配模式。如果您想保持不匹配的行,请删除-n p

  

输入文件:

-n p
  

输出新文件:

bigspeedpro.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
1.1.1.1 Intel::DOMAIN   from http://abcd.com/bl/BOOT via intel.criticalstack.com     F
bigspeedpro.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
123.1.1.1 Intel::DOMAIN   from http://abcd12.bcd.com/bl/BOOT via intel.criticalstack.com     F
bigspeedpro.com Intel::DOMAIN   from https://malc0de.com/bl/BOOT via intel.criticalstack.com     F
87.1.4.1 Intel::DOMAIN   from http://abcdtdd.com/bl/BOOT via intel.criticalstack.com     F
bigspeedpro.com Intel::DOMAIN   from http://malc0de.com/bl/BOOT via intel.criticalstack.com     F
192.168.1.1 Intel::DOMAIN   from www.abcdbc12a.bdf12.com/bl/BOOT via intel.criticalstack.com     F

更新:我更新了我的答案,稍微改了一下,现在它可以处理1.1.1.1 abcd 123.1.1.1 abcd12.bcd 87.1.4.1 abcdtdd 192.168.1.1 abcdbc12a.bdf12 并返回http/https/wwwhttps/https/www之间的内容。它的在线人数相对较短。

相关问题