0

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

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

任何帮助表示赞赏。该文件包含大约 100 万条以上的记录,因此我很高兴采用不使用 sed/awk 并提高性能的路线。

4

3 回答 3

3

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

文件.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
于 2016-12-23T17:48:37.947 回答
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) 来保存它,除了删除任何将其与已经存在的内容分开的换行符 ( x;s/^\n//;s/\n/ /;x)。(如果你想在你的输出中使用标签,把它们放在这里我放了几个空格的地方。)

  • 如果您遇到与您的 Accept-Language 模式匹配的行,请在添加任何内容之前刷新保留空间。打印并清除它 ( x;p;s/.*//;x)。然后像往常一样进行附加和诸如此类的事情。

  • 将第一行和最后一行与其他所有行区别对待:不要在仅读取第一行后刷新保持空间(1bgo跳过第一行,向下到标记的位置:go),并且总是在读取最后一行后刷新保持空间(${ x;p; }

于 2016-12-23T17:34:34.533 回答
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" ....

于 2016-12-25T10:59:53.930 回答