合并与正则表达式不匹配的行

时间:2016-12-23 17:16:46

标签: regex file awk sed http-accept-language

我有一个包含来自网络的日志的文件;它的简化版本如下:

en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
Unix
Linux
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
START
Solaris
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
Aix
SCO

我尝试了几个正则表达式组合来识别Accept-Language,这是使用以下awk / sed的每一行的开头:

/^[a-z]{2}(-[A-Z]{2})?/
/\*|[A-Z]{1,8}(-[A-Z0-9]{1,8})*/i  
/([^-;]*)(?:-([^;]*))?(?:;q=([0-9]\.[0-9]))?/

到目前为止,我还没有设法让awk / sed给我以下结果:

en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;    Unix    Linux
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;    STAR    Solaris
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;    Aix    SCO

感谢任何帮助。该文件包含大约1百万条记录,因此我很乐意沿着不使用sed / awk并提高性能的路线前进。

3 个答案:

答案 0 :(得分:3)

根据观察,我们可以区分=上的两种类型的线,你可以使用这个awk脚本:

<强> file.awk

$0 ~ /=/ { printf("%s%s", v,$0)
           v="\n"
           next
         } 
         { printf("\t%s", $0) } 
END      { printf("\n") }

您可以像这样使用它:awk -f file.awk yourfile

    第一行
  • v为空,之后包含换行符
  • 对于=行,我们打印$0前面有v
  • 对于其他行(请注意第一个操作中的next),我们打印的$0没有换行符,但\t为分隔

答案 1 :(得分:0)

只是为了好玩,这是一个sed解决方案:

sed -ne 1bgo \
   -e '/^[a-z][a-z]-[A-Z][A-Z]/ { x;p;s/.*//;x; };:go' \
   -e 'H;x;s/^\n//;s/\n/  /;x;${ x;p; }' < input

它的工作原理如下:

  • 读取每一行但不是立即打印,而是通过将其附加到保留空间(H)来保存它,除了删除任何将其与已存在的空格分开的新行({{1 }})。 (如果你想在输出中添加标签,请将它们放在我放置几个空格的位置。)

  • 如果您遇到与您的Accept-Language模式匹配的行,请在向其追加任何内容之前刷新保留空间。打印并清除它(x;s/^\n//;s/\n/ /;x)。然后像往常一样继续附加和诸如此类的东西。

  • 将第一行和最后一行与其他行区别对待:在读取第一行(x;p;s/.*//;x跳过该行后,直到标记为1bgo的位置)时,永远不要刷新保留空间,并且在阅读完最后一行(:go

  • 后始终刷新保留空间

答案 2 :(得分:0)

$ awk '/[a-z]{2}-[A-Z]{2}/ { print b; b=$0; next }  # @xx-XX empty buffer, refill
                           { b=b OFS $0 }           # otherwise append to buffer
                       END { print b }' file        # dump the buffer in the end

en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd;
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd; Unix Linux
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd; START Solaris
en-GB,en-US;q=0.8,en    jsdjpksdkskd;lkskd; Aix SCO

您将获得一个空行以启动输出。此外,如果需要,请在输出上使用制表符分隔符:awk -v OFS="\t" ...