awk分割字符串忽略双引号中空格的问题

622 views
Skip to first unread message

Perchouli Chen

unread,
Sep 23, 2013, 6:55:47 PM9/23/13
to sh...@googlegroups.com
要处理的字符串是一些nginx日志,例如:
"127.0.0.1" "21" "" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)" "-" "2013-09-23T10:00:04+08:00" "“

如果是要匹配双引号里的内容,用正则就行,但空格是awk默认的分隔符,于是双引号中的空格也被当成分割符了,上例中的浏览器记录带了空格,awk结果成了:
[127.0.0.1, 21, Mozilla/4.0 ....] 

在SO上有个问题很类似,是用条件来做,但我尝试了没成功:

也可以用其他方式处理,但肯定是awk最简单高效了。初学bash,希望能得到各位的指点,非常感谢。

Chaos Eternal

unread,
Sep 23, 2013, 7:12:27 PM9/23/13
to sh...@googlegroups.com
2013/9/24 Perchouli Chen <jp.ch...@gmail.com>:
> 要处理的字符串是一些nginx日志,例如:
> "127.0.0.1" "21" "" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;
> .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)" "-" "2013-09-23T10:00:04+08:00"
> "“

针对这种特殊情况,可以考虑用 " " 做分隔符,例如:
echo '"abcd d" "efgh" "kkk adad"'|awk -F'" "' '{print $2}'

如果要兼顾头尾的",
还可以写成这样:
echo '"abcd d" "efgh" "kkk adad"'|awk -F'(" "|^"|"$)' '{print $2}'

但是:如果输入是一般的CSV规范的格式的话,即,引号可以选择性的出现,比如
field1 "field2 with delimiter" field3
上面的办法就无能为力了。

这就是正则表达式的局限之处。
引王垠的说法是,这玩意用多了也不见得有多好,很多时候不如不用。



>
> 如果是要匹配双引号里的内容,用正则就行,但空格是awk默认的分隔符,于是双引号中的空格也被当成分割符了,上例中的浏览器记录带了空格,awk结果成了:
> [127.0.0.1, 21, Mozilla/4.0 ....]
>
> 在SO上有个问题很类似,是用条件来做,但我尝试了没成功:
> http://stackoverflow.com/questions/6619619/awk-consider-double-quoted-string-as-one-token-and-ignore-space-in-between
>
> 也可以用其他方式处理,但肯定是awk最简单高效了。初学bash,希望能得到各位的指点,非常感谢。
>
> --
> -- You received this message because you are subscribed to the Google Groups
> Shanghai Linux User Group group. To post to this group, send email to
> sh...@googlegroups.com. To unsubscribe from this group, send email to
> shlug+un...@googlegroups.com. For more options, visit this group at
> https://groups.google.com/d/forum/shlug?hl=zh-CN
> ---
> 您收到此邮件是因为您订阅了 Google 网上论坛的“Shanghai Linux User Group”论坛。
> 要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到 shlug+un...@googlegroups.com
> 要查看更多选项,请访问 https://groups.google.com/groups/opt_out

雷钦

unread,
Sep 23, 2013, 10:13:31 PM9/23/13
to sh...@googlegroups.com
On 2013-09-24 07:12:27 +0800, Chaos Eternal wrote:
> 2013/9/24 Perchouli Chen <jp.ch...@gmail.com>:
> > 要处理的字符串是一些nginx日志,例如:
> > "127.0.0.1" "21" "" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;
> > .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)" "-" "2013-09-23T10:00:04+08:00"
> > "“
>
> 针对这种特殊情况,可以考虑用 " " 做分隔符,例如:
> echo '"abcd d" "efgh" "kkk adad"'|awk -F'" "' '{print $2}'
>
> 如果要兼顾头尾的",
> 还可以写成这样:
> echo '"abcd d" "efgh" "kkk adad"'|awk -F'(" "|^"|"$)' '{print $2}'
>
> 但是:如果输入是一般的CSV规范的格式的话,即,引号可以选择性的出现,比如
> field1 "field2 with delimiter" field3
> 上面的办法就无能为力了。
>
> 这就是正则表达式的局限之处。
> 引王垠的说法是,这玩意用多了也不见得有多好,很多时候不如不用。
>
>
>
> >
> > 如果是要匹配双引号里的内容,用正则就行,但空格是awk默认的分隔符,于是双引号中的空格也被当成分割符了,上例中的浏览器记录带了空格,awk结果成了:
> > [127.0.0.1, 21, Mozilla/4.0 ....]
> >
> > 在SO上有个问题很类似,是用条件来做,但我尝试了没成功:
> > http://stackoverflow.com/questions/6619619/awk-consider-double-quoted-string-as-one-token-and-ignore-space-in-between
> >
> > 也可以用其他方式处理,但肯定是awk最简单高效了。初学bash,希望能得到各位的指点,非常感谢。

可以尝试一下 csvtool

csvtool -t ' ' col 3 somefile.csv

Perchouli

unread,
Sep 24, 2013, 3:22:04 AM9/24/13
to sh...@googlegroups.com, 雷钦
感谢回复,这个日志各种数据都有,也有url记录,只能确保数据都在双引号内,有几个字段是用空格分割的,有几个字段是连在一起的,比如:
 """0" "- " "-" "2013-09-23T10:00:04+08:00" "-" "400" (是一条400的记录,没有参数,ip部分就和接下来的字段连在一起了)

是否能匹配到双引号里的内容?实在不行我就还是去改nginx的格式吧。

感谢leiqin推荐csvtool来处理,只是这数据全市 【 "Bad '"' in quoted field") 】的状态用不了。


--
-- You received this message because you are subscribed to the Google Groups Shanghai Linux User Group group. To post to this group, send email to sh...@googlegroups.com. To unsubscribe from this group, send email to shlug+un...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/shlug?hl=zh-CN
---
您收到此邮件是因为您订阅了 Google 网上论坛的“Shanghai Linux User Group”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到 shlug+un...@googlegroups.com
要查看更多选项,请访问 https://groups.google.com/groups/opt_out



--

Very Respectfully.Your obedient servant
Perchouli

Chaos Eternal

unread,
Sep 24, 2013, 3:33:23 AM9/24/13
to sh...@googlegroups.com
鉴于HTTP日志里面不会出现不可打印字符,其实你可以nginx用\007这种字符做分隔符的。

2013/9/24 Perchouli <jp.ch...@gmail.com>:

依云

unread,
Sep 25, 2013, 11:33:51 AM9/25/13
to sh...@googlegroups.com
On Tue, Sep 24, 2013 at 03:22:04PM +0800, Perchouli wrote:
> 感谢回复,这个日志各种数据都有,也有url记录,只能确保数据都在双引号内,有几个字段是用空格分割的,有几个字段是连在一起的,比如:
> """0" "- " "-" "2013-09-23T10:00:04+08:00" "-" "400"
> (是一条400的记录,没有参数,ip部分就和接下来的字段连在一起了)
>
> 是否能匹配到双引号里的内容?实在不行我就还是去改nginx的格式吧。
>
> 感谢leiqin推荐csvtool来处理,只是这数据全市 【 "Bad '"' in quoted field") 】的状态用不了。

看了很久,没看到你处理的目的。仅仅是匹配双引号间的内容的话,在 $0 里取就
可以了吧?

--
Best regards,
lilydjwg

Linux Vim Python 我的博客:
http://lilydjwg.is-programmer.com/
--
A: Because it obfuscates the reading.
Q: Why is top posting so bad?

Bin Sun Sunny

unread,
Sep 26, 2013, 1:24:59 AM9/26/13
to sh...@googlegroups.com
感觉他想要把所有字段分开, 然后提取想用的 $1, $3 .... , 但是如果只用空格, 引号中也会有空格. 如果用 " " , 还是无法解决有时候字段合并的问题.

依云

unread,
Sep 26, 2013, 7:08:35 AM9/26/13
to sh...@googlegroups.com
On Wed, Sep 25, 2013 at 10:24:59PM -0700, Bin Sun Sunny wrote:
> 感觉他想要把所有字段分开, 然后提取想用的 $1, $3 .... , 但是如果只用空格, 引号中也会有空格. 如果用 " " ,
> 还是无法解决有时候字段合并的问题.

传给 grep -oP '(?<=")[^']+(?=")' 处理呢?
Reply all
Reply to author
Forward
0 new messages