【问题标题】:awk multiple delimiter and print multiple columnawk 多个分隔符并打印多列
【发布时间】:2013-05-23 10:09:46
【问题描述】:

我正在尝试从日志输出创建 CSV 文件

以两行日志文件为例:

May 24 2013 18:13:24 ROUTER1 %%01IFNET/4/UPDOWN(l): The state of interface GigabitEthernet0/0/22 was changed to DOWN.
May 24 2013 17:59:33 ROUTER1 %%01FIB/3/REFRESH_END(l): FIB refreshing end, the refresh group map is 0!

预期输出:

May 24 2013 18:13:24,ROUTER1,01IFNET,4,UPDOWN,The state of interface GigabitEthernet0/0/22 was changed to DOWN.
May 24 2013 17:59:33,ROUTER1,01IFNET,3,REFRESH_END,FIB refreshing end, the refresh group map is 0!

我可以设法用这个 awk 命令得到一些正确的部分:

cat test.log | awk -F'[" "%%/(l)]' '{print $1" "$2" "$3","$4","$5","$8","$9","$10","}'

输出:

May 24 2013 18:13:24,ROUTER1,01IFNET,4,UPDOWN,
May 24 2013 17:59:33,ROUTER1,01IFNET,3,REFRESH_END,

但是如何捕获"(l):"之后的多列描述文本,例如“FIB刷新结束,刷新组图为0!”或“ 接口 GigabitEthernet0/0/22 的状态已更改为 DOWN。"。请指教。

【问题讨论】:

标签: awk


【解决方案1】:

由于这是单行的简单替换,我只使用 sed,例如:

$ cat file
May 24 2013 18:13:24 ROUTER1 %%01IFNET/4/UPDOWN(l): The state of interface GigabitEthernet0/0/22 was changed to DOWN.
May 24 2013 17:59:33 ROUTER1 %%01FIB/3/REFRESH_END(l): FIB refreshing end, the refresh group map is 0!

$ sed -r 's/(([^ ]+ +){3}[^ ]+) +([^ ]+)[ %]+([^/]+)\/([^/]+)\/([^(]+)[^ ]+ +(.*)/\1,\3,\4,\5,\6,\7/' file
May 24 2013 18:13:24,ROUTER1,01IFNET,4,UPDOWN,The state of interface GigabitEthernet0/0/22 was changed to DOWN.
May 24 2013 17:59:33,ROUTER1,01FIB,3,REFRESH_END,FIB refreshing end, the refresh group map is 0!

但如果您愿意,这里有一个 awk 解决方案:

$ awk -F' %%|[(][^)+][)]: ' -v OFS="," '{$1=substr($1,1,20) OFS substr($1,22); gsub(/\//,OFS,$2)}1' file
May 24 2013 18:13:24,ROUTER1,01IFNET,4,UPDOWN,The state of interface GigabitEthernet0/0/22 was changed to DOWN.
May 24 2013 17:59:33,ROUTER1,01FIB,3,REFRESH_END,FIB refreshing end, the refresh group map is 0!

并不是说这不会从您的第一行输入中删除“千兆...”文本,因为您没有说明如何识别它 - 您是想在“界面”之后删除文本还是以“ Gigabit”或在一定数量的空格或其他东西之后?

【讨论】:

  • 感谢您的回复.. 实际上我不想去掉“Gigabit...”..不幸的是这是一个打字错误。 :)
【解决方案2】:

我希望删除“界面”之后的东西不是错字...

又脏又快:(不过应该有更好的方法..)

awk -F'\\(l\\): ' -v OFS="," '{gsub(" %%|/"," ",$1);gsub(/ /,",",$1);for(i=1;i<=3;i++)sub(/,/," ",$1)}$2~/of interface /{gsub(/interface.*/,"interface",$2)}1' file

给予

May 24 2013 18:13:24,ROUTER1,01IFNET,4,UPDOWN,The state of interface
May 24 2013 17:59:33,ROUTER1,01FIB,3,REFRESH_END,FIB refreshing end, the refresh group map is 0!

【讨论】:

  • 你是对的..确实是一个错字:| :(我的错..对不起。实际上我无意删除“界面”之后的文字..
  • 还是感谢您的回复 :)
【解决方案3】:

awk 可以处理多个分隔符:

$ awk -F'[(/% ]' '{printf "%s",$1" "$2" "$3" "$4" "$5","$8","$9","$10",";for(i=12;i<=NF;i++)printf "%s ",$i;print ""}' file
May 24 2013 18:13:24 ROUTER1,01IFNET,4,UPDOWN,The state of interface GigabitEthernet0 0 22 was changed to DOWN.
May 24 2013 17:59:33 ROUTER1,01FIB,3,REFRESH_END,FIB refreshing end, the refresh group map is 0!

【讨论】:

  • 谢谢,正是我需要的!
  • sudo_O,-F'[(/% ]' 匹配什么?
  • -F 用于设置数据分隔符,其值为正则表达式[(/% ],它定义包含字符(/% 或单个字符的字符类空间。基本上,类中的任何字符都不会被视为数据,而是作为分隔符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 2014-07-24
  • 1970-01-01
  • 2014-05-27
相关资源
最近更新 更多