【问题标题】:Unix scripting in bash to search logs and return a specific part of a specific log filebash 中的 Unix 脚本来搜索日志并返回特定日志文件的特定部分
【发布时间】:2015-11-25 04:44:10
【问题描述】:

我敢说,我主要是一个 Windows 人(请不要太早把我击倒),虽然我过去在 Linux 中玩过(主要是命令行)。 我有一个过程,我必须偶尔经历一次,本质上是在一个目录(和子目录)中的所有日志文件中搜索某个文件名,然后从所述日志文件中获取一些内容。

我的第一步是

grep -Ril <filename or Partial filename you are looking for> log/*.log

据此我有日志文件名,我vi 可以找到它发生的位置。 澄清一下:grep 正在查看所有日志文件,查看 -Ril 之后的文件名是否出现在其中。

vi log/<log filename>
/<filename or Partial filename you are looking for>

我做了几次j 以找到 CDATA,然后我有一个需要提取的 URL,然后在 putty 中进行选择,复制并粘贴到浏览器中。 然后我退出vi 而不保存。


FRED1 triggered at Mon Aug 31 14:09:31 NZST 2015 with incoming file /u03/incoming/fred/Fred.2
Fred.2
start grep
end grep
Renamed to Fred.2.20150831140931

    <?xml version="1.0" encoding="UTF-8"?>
    <runResponse><runReturn><item><name>runId</name><value>1703775</value></item><item><name>runHistoryId</name><value>1703775</value></item><item><name>runReportUrl</name><value>https://<Servername>:<port and path>b1a&amp;sp=l0&amp;sp=l1703775&amp;sp=l1703775</value></item><item><name>displayRunReportUrl</name><value><![CDATA[https://<Servername>:<port and path2>&sp=l1703775&sp=l1703775]]></value></item><item><name>runStartTime</name><value>08/31/15 14:09</value></item><item><name>flowResponse</name><value></value></item><item><name>flowResult</name><value></value></item><item><name>flowReturnCode</name><value>Not a Return</value></item></runReturn></runResponse>
    filePath=/u03/incoming/fred&fileName=Fred.2.20150831140931&team=dps&direction=incoming&size=31108&time=Aug 31 14:09&fts=nzlssftsd01

----------------------------------------------------------------------------------------
FRED1 triggered at Mon Aug 31 14:09:31 NZST 2015 with incoming file /u03/incoming/fred/Fred.3
Fred.3
start grep
end grep
Renamed to Fred.3.20150999999999

    <?xml version="1.0" encoding="UTF-8"?>
    <runResponse><runReturn><item><name>runId</name><value>1703775</value></item><item><name>runHistoryId</name><value>1703775</value></item><item><name>runReportUrl</name><value>https://<Servername>:<port and path>b1a&amp;sp=l0&amp;sp=l999999&amp;sp=l9999999</value></item><item><name>displayRunReportUrl</name><value><![CDATA[https://<Servername>:<port and path2>&sp=l999999&sp=l999999]]></value></item><item><name>runStartTime</name><value>08/31/15 14:09</value></item><item><name>flowResponse</name><value></value></item><item><name>flowResult</name><value></value></item><item><name>flowReturnCode</name><value>Not a Return</value></item></runReturn></runResponse>
    filePath=/u03/incoming/fred&fileName=Fred.3.20150999999999&team=dps&direction=incoming&size=31108&time=Aug 31 14:09&fts=nzlssftsd01

我要获取的是CDATA[https://&lt;Servername&gt;:&lt;port and path2&gt;&amp;sp=l999999&amp;sp=l999999]Fred.3.20150999999999 的URL,由Renamed to Fred.3.20150999999999 行指示。

这可能吗? (我对 XML 格式表示歉意,但它与日志文件中的完全相同。)

提前致谢,
电话

【问题讨论】:

  • 我粘贴的日志的sn-p只有一部分。有多个这样的条目,因此我们需要找到与要提取的文件名关联的条目。 (在上面的 sn-p 中,文件名是 Fred.2)

标签: bash scripting redhat


【解决方案1】:
sed -n 's@\(.*CDATA\[\)\(.*\)\(\]\].*\)@\2@p'  <logfile>

-n 禁止自动打印图案空间

@ - 作为 sed 模式分隔符

( ) - 对模式进行分组

\2 - 第二个模式

p - 打印

**更新 - grep 文件模式**

grep -Ril <filename or Partial filename you are looking for> log/*.log | xargs sed -n "/<pattern>/,/filePath=/p" | sed -n 's@\(.*CDATA\[\)\(.*\)\(\]\].*\)@\2@p'

xargs 将前一个命令的输出作为输入文件。

如果模式是 Fred.3.20150999999999,第一个 sed 将从匹配的模式打印到 filePath=,下一个 sed 将在其中提取 CDATA。

【讨论】:

  • 嗨,这很好用,但问题是它返回所有 CDATA url。日志文件有多个。所以我 grep 查找日志文件名,然后获取 URL,您需要根据文件名在日志中找到正确的部分并仅提取下一个 CDATA
  • 更新了答案以满足您的要求。如果您的模式保持不变,您也可以使用以下命令。 sed -n 's@\(.*CDATA\[\)\(.*\)\(\]\].*\)@\2@p' log/&lt;pattern&gt;*.log
  • 不幸的是,它仍在抓取所有 CDATA URL,而不仅仅是与您要查找的 sed 需要找到“重命名为 Fred.3.20150999999999”(因为那是grep 正在查找的日志中的文件名),然后获取之后的第一个 CDATA URL。
  • 您是否尝试过 grep 命令然后通过管道传输到 sed。如果是这样,您可以仅粘贴 grep 的操作
  • 是的,我尝试了通过 sed 管道传输的 grep,如上所述。 grep -Ril 只返回日志文件名 log/test.logging.log 如上所述通过 sed 管道查找 grep 找到的日志中所有 CDATA 的 URL。对于 grep,我可以将其设为 grep -Ri -a1 并输出我所追求的特定条目的 XML,但 sed 不太喜欢这样。
【解决方案2】:

虽然您的grep 命令可用于定位文件,但find 命令更灵活且更合适。定位日志文件的基本用途类似于:

find /path/to/logdir -type f -name "partial*.log"

这将在/path/to/logdir 下递归搜索名称与模式"partial*.log" 匹配的文件-type f

隔离 url 可以与其他答案类似,但在这里使用多个表达式,您可以使用以下方法隔离 url:

sed -e 's/^.*CDATA\[\(http[^]]*\).*$/\1/' <logfilename> \
    -e '/^$/'d \
    -e '/^[ \t\n].*$/'d

输出:

https://<Servername>:<port and path2>&sp=l1703775&sp=l1703775

第一个表达式将 url 本身与您的 &lt;logfilename&gt; 隔离开来,第二个表达式抑制任何空白行,最后,第三个表达式删除以 [空格、制表符或换行符] 开头的返回片段。

如果您可以调整您的 find 命令以可靠地返回您需要从中检索 url 的确切文件,那么您可以将您的 findsed 命令一起编写为:

sed -e 's/^.*CDATA\[\(http[^]]*\).*$/\1/' \
    $(find /path/to/logdir -type f -name "partial*.log") \
    -e '/^$/'d \
    -e '/^[ \t\n].*$/'d

您只需使用 命令替换&lt;logfilename&gt; 替换为包含在 $(...) 中的 find 命令。

注意有许多不同的方式来编写sed 替换,有些可能比这个更优雅,但这就是sed 的强大之处。试一试,如果您遇到问题,请告诉我。我希望这会有所帮助。

【讨论】:

  • 嗨,这很好用,但问题是它返回第一个 CDATA url,然后返回日志的其余部分。日志文件有多个条目。所以我 grep 查找日志文件名,然后获取 URL,您需要根据我在 grep 中使用的文件名在日志中找到正确的部分并仅提取下一个 CDATA。
  • 好的,我将不得不考虑更多地处理多个条目。今晚我会有更多的时间。
  • @telsum 处理多次出现,您可以重新排列命令。试试grep CDATA logfile.log | sed -e 's/^.*CDATA\[\(http[^]]*\).*$/\1/' -e '/^$/'d -e '/^[ \t\n].*$/'d 我没有要测试的完整数据文件,但这会从您的日志文件中获取包含CDATA 的每一行,并通过sed 命令过滤每一行。
  • 谢谢大卫,你的答案和接受的答案教会了我很多关于 sed 的知识,最初的 grep 是找到其中包含文件名的模式或文字的日志文件名,并返回日志文件包含那个。然后下一部分必须从 grep 中的所述日志文件中找到该模式或文字出现的位置,并直接从 CDATA 中提取 URL。非常感谢,但是这两个答案都让我看到了 sed 的力量。
猜你喜欢
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-16
相关资源
最近更新 更多