我有一个包含来自网络的日志的文件;它的简化版本如下:
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并提高性能的路线前进。
答案 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" ...
。