用grep搜索文件,只输出部分行

时间:2017-10-02 21:23:13

标签: linux bash sed grep

我正在寻找日志文件并尝试在我的结束文件中获得更简洁的输出。如果我想要一个我想要的值,然后格式化输出以删除除日期和网址之外的任何内容。

例如,这里是文件的一行。

  

Sep 25 08:07:51 10.20.30.40 FF_STUFF []:1545324890 1 55.44.33.22 10.9.8.7 - 10.60.154.41 { {3}} 0 BYF ALLOWED CLEAN 2 1 0 0 0( - )0 - 0 - 0 sqm.microsoft.com - [ - ] sqm.microsoft.com - - 0

如果需要,我想做一个grep或更好的命令,输出到只列出粗体条目的.txt文件。基本上列出日期和URL。那么我怎么告诉它列出前15个字符,包括空格,然后找到第一个http / https并列出所有内容,直到第一个空格?每条线的长度和长度都不一样,所以我不能只按字符位置。

所以我的输出将是

  

Sep 25 08:07:51 http://website.com

谢谢。

5 个答案:

答案 0 :(得分:1)

您无法在-o中轻松使用grep选项,因为您有两种模式,由可变数量的字符分隔(-o将打印完整的匹配部分)

如果您只想提取网址,这就足够了:

$ grep -oE 'https?:[^ ]+' file
http://website.com

但要提取日期和网址,可能最简单的解决方案是 GNU awk

$ awk '{ match($0, /https?:[^ ]+/, url); print $1, $2, $3, url[0]; }' file
Sep 25 08:07:51 http://website.com

您打印前三个字段($1$3,以空格分隔),然后搜索match()的网址(假设它不包含空格,即空格字符是始终正确转义; +%20),然后打印找到的第一个网址(日期之后)。

如果您有 POSIX awk (或使用gawk标记调用--posix),解决方案会更加冗长,因为POSIX {{ 1}}不支持将匹配的部分保存到数组中(第三个参数match()),并且当找到匹配项时,您必须使用substr()显式提取URL:

url

答案 1 :(得分:0)

为了补充@ randomir的答案,我们也可以使用sed

$ sed 's/\(.\{15\}\).*\(https\?:\/\/[^ ]\+\).*/\1 \2/' < input.txt > output.txt

此模式假定前15个字符组成日期,并且URL不包含空格。它适用于 http https 网址。

修改 - 为了解决问题 - 为了学习,我们还可以调用sed来执行grep之类的行匹配操作:

sed -n '/10\.45\.19\.151/p' < input.txt

...将输出 input.txt 中包含IP地址10.45.19.151的所有行。 -n选项会抑制每行的输出。我们将此选项与 p 命令组合到打印,只匹配与模式匹配的行。

我们可以将此方法与第一个命令合并为“grep”,用于行使用单个命令对它们进行转换:

sed -n '/<line-match-pattern>/ s/<...>/<...>/ p' < input.txt

...将仅选择与<line-match-pattern>匹配的行,执行替换并输出结果。为了说明,这里是一个使用评论中提供的信息的例子:

sed -n '/10\.45\.19\.151/ s/\(.\{15\}\).*\(https\?:\/\/[^ ]\+\).*/\1 \2/ p' \
    < messages-20171001 \
    > /backup/mikesanders-fwlog-10012017.txt

答案 2 :(得分:0)

awk '{match($0,/http[^com]*/);print $1,$2,$3,substr($0,RSTART,RLENGTH+3)}'  Input_file

上述代码说明:

awk '{
match($0,/http[^com]*/);                  ##Using match default utility of awk where I am searching for regex where it will look for string http till string com comes.
print $1,$2,$3,substr($0,RSTART,RLENGTH+3)##Now printing the 1st, 2nd and 3rd column which are date and time in current line and printing sub string of current line where it should start substring from the value of RSTART till value of RLENGTH(which will be http complete URL actually). Now point to be noted here variables RSTART and RLENGTH are default variables of awk which will be set once a regex match is found in match utility of awk.
}
' Input_file                              ##Mentioning the Input_file name here.

答案 3 :(得分:0)

您可以使用grep -o匹配所需的每个行部分,然后重新组合grep返回的行:

$ grep -Eo '^.{15}|https?://[^ ]+' f | paste - -
Sep 25 08:07:51 http://website.com

请注意,在FreeBSD或OSX中,他们使用的旧版本的GNU grep(2.5.1)是错误的,因此需要更明确的日期识别:

$ grep -Eo '[A-Z][a-z]{2} ([0-9]{2}[ :]){3}[0-9]{2}|https?://[^ ]+' f | paste - -
Sep 25 08:07:51 http://website.com

FreeBSD中的一种解决方法是使用bsdgrep,它在功能上等同于gnu grep但没有错误。在MacOS中,可能需要使用自制软件或macports安装替代方案..或者在另一个答案中使用POSIX awk解决方案。

无论如何,在这两种情况下,正则表达式由两个表达式组成,这些表达式在|之前与or-bar(https)连接。第一个子表达式与您的日期匹配,第二个子表达式与您的网址匹配。

只要每个输入行都包含与这两个元素匹配的文本,就应该从每个日志条目的grep获得两行输出。然后paste将它们重新组合成一行。

答案 4 :(得分:0)

只需1个命令行,如:

msr -p my.log -t "^(.*?\d+:\d+:\d+).*?(https?://\S+).*" -o '$1 $2' -PIC > output.txt

  • 如果first 15 characters比模式"^(.*?\d+:\d+:\d+)"更可靠:

    使用"^(.{15})",例如:-t "^(.{15}).*?(https?://\S+).*"

  • 如果您希望进一步过滤包含一个ip 10.9.8.7作为plaint-text(-x):

    msr -p my.log -x 10.9.8.7 -t "^(.*?\d+:\d+:\d+).*?(https?://\S+).*" -o '$1 $2'

  • 如果必须包含更多IP,例如10.9.8.7 10.9.8.8 10.9.8.9,或进一步处理:

    msr -p my.log -t "^(.*?\d+:\d+:\d+).*?(https?://\S+).*" -o '$1 $2' -PAC | msr -t "10\.9\.8\.[7-9]" -PAC > output.txt

msr.exe / msr.gcc*对于此类ETL工作(加载 - >提取 - &gt;转换或替换文件)single exe toolin my open project,大约1.6MB,没有依赖关系,跨平台版本加上x86 / x64版本。

  • 以递归方式加载文件(-r)并过滤目录名称,文件名,时间,大小如:

    -r -p dir1,dirN,file1,fileN -f "\.(log|txt)$" --w1 2017-09-25--nf "excluded-files" --nd "excluded-directories"--s1 1.5MB --s2 30MB--w2 "2017-09-30 22:30:50"等。

  • 与<{1}}或Regex不同的

    一般 sed提取,与awk /完全相同C++ / C# / Java /等:

    Scala忽略大小写:添加-t "^(.*?\d+:\d+:\d+).*?(https?://\S+).*",如:-i-i -t

  • 转换输出,如:

      适用于Linux的
    • -it或Windows上的-o '$1 $2' / Cygwin
    • Powershell适用于Windows -o "$1 $2"CMD console window / *.bat个文件。

见下面的截图: Extract log and transform output

如果您使用的是Linux,则只需运行*.cmdmsr.gcc48 32位计算机即可。只需运行exe即可获得用法和示例,或查看有关performance comparison的在线文档(使用Linux系统工具 grep 和Windows系统工具 findstr ),内置文档,如:msr on CentOS,丰富多彩的vivid demo on Windows