【问题标题】:Simple regular expression parsing in bashbash 中的简单正则表达式解析
【发布时间】:2010-10-19 12:06:49
【问题描述】:

我想解析一个日志文件 (log.txt),其中包含与以下类似的行:

2010-10-19 07:56:14 URL:http://www.website.com/page.php?ID=26 [13676] -> "www.website.com/page.php?ID=26" [1]
2010-10-19 07:56:14 URL:http://www.website.com/page.php?ID=44 [14152] -> "www.website.com/page.php?ID=44" [1]
2010-10-19 07:56:14 URL:http://www.website.com/page.php?ID=13 [13681] -> "www.website.com/page.php?ID=13" [1]
2010-10-19 07:56:14 ERROR:Something bad happened
2010-10-19 07:56:14 ERROR:Something really bad happened
2010-10-19 07:56:15 URL:http://www.website.com/page.php?ID=14 [12627] -> "www.website.com/page.php?ID=14" [1]
2010-10-19 07:56:14 ERROR:Page not found
2010-10-19 07:56:15 URL:http://www.website.com/page.php?ID=29 [13694] -> "www.website.com/page.php?ID=29" [1]

你可能已经猜到了:

1) 我需要从每一行中提取这部分:

2010-10-19 07:56:15 URL:http://www.website.com/page.php?ID=29 [13694] -> "www.website.com/page.php?ID=29" [1]
------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2) 这部分转到另一个文件 (log.html),如下所示:

<a href="http://www.website.com/page.php?ID=29">http://www.website.com/page.php?ID=29</a>

我需要通过 bash 脚本执行此操作,该脚本将在 *nix 平台上运行。我对 shell 编程一无所知,因此非常感谢详细的脚本,指向 bash 编程参考的指针就可以了。

【问题讨论】:

  • Bash 不做正则表达式。使用 grep 查找匹配行,然后使用 awk 提取相关位。

标签: linux bash scripting shell


【解决方案1】:

这是一个 bash 解决方案

#!/bin/bash
exec 4<"log.txt"
while read -r line<&4
do
  case "$line" in
    *URL:* )
      url="${line#*URL:}"
      url=${url%% [*}
      echo "<a href=\"${url}\">${url}</a>"
  esac
done
exec 4<&-

【讨论】:

    【解决方案2】:

    这应该可行:

    sed -n 's%^.* URL:\(.*\) \[[0-9]*\] -> .*$%<a href="\1">\1</a>%p' log.txt
    

    【讨论】:

    • 真的需要圆括号前的反斜杠吗?
    • 我在反斜杠和引号方面度过了一段糟糕的时光,但最终让它发挥了作用: sed -n "s@.\+ URL:\([^ ]\+\) .\+@\ 1@p" 日志.txt | sed "s@&@\&@" > url.txt
    【解决方案3】:

    这是一个小的 awk 脚本,应该可以满足您的需要。

    awk '/URL:/ { sub(/^URL:/,"", $3); printf "<a href=\"%s"\">%s</a>\n", $3, $3; }'
    

    【讨论】:

      【解决方案4】:

      sed 怎么样:

      sed -n 's/.*URL:\([^ ]\+\) .*/<a href="\1">\1<\/a>/;/<a href/p' logfile
      

      (请注意:您可以更正确地处理 URL 部分,例如通过它前面的日期字符串的长度,但我只是懒惰。)

      【讨论】:

        【解决方案5】:

        类似这样的:

        while read line
        do
                URL=$(echo $line | egrep -o 'URL:[^ ]+' | sed  's/^URL://')     
                if [ -n "$URL" ]; then
                        echo "<a href=\"$URL\">$URL</a>" >> output.txt
                fi  
        done < input.txt
        

        【讨论】:

        • 使用egrep读取文件比外部while循环快。 egrep -o 'URL:[^ ]+' input.txt| sed .....|while read ....。顺便说一句,egrep 现在是 grep -E
        • @ghostdog74:感谢egrep 的提示。但没有得到第一部分。
        • 您有一个外部 while 读取循环来迭代文件,并且对于每一行,您正在调用 2 个外部命令,egrepsed 使用管道。这是昂贵的操作。因此建议使用egrep 来迭代文件,因为它经过优化可以更有效地遍历文件,无论大小。不,您的脚本没有错,只是在速度方面没有优化,仅此而已。 :)
        • 我使用该脚本的一部分对文件进行后处理。
        猜你喜欢
        • 2011-04-11
        • 1970-01-01
        • 2021-11-27
        • 1970-01-01
        • 1970-01-01
        • 2012-10-17
        • 1970-01-01
        • 1970-01-01
        • 2014-03-22
        相关资源
        最近更新 更多