最近在做日志分析,linux C 的开发环境,在对每行日志进行处理的时候,手下一个小伙用的是逐字节拆分成字段。

刚开始没注意,后来每天10几G的日志上来后,发现除了速度特别慢以外,还经常出问题,遇到错误格式的日志就直接崩溃。。。

拿过来帮他改的时候,觉得这里完全可以用sscanf来进行处理,于是google+man 以及半天的测试以后,终于找到了一个比较合理的格式字符串

"%s - - %s %*[/"]%s %1000[^/"]/" %d %d %*[/"]%1000[^/"]/" %*[/"]%1000[^/"] %*[/"]%s %d/n"

原日志格式为

58.56.110.98 - - 1264348800 "GET http://www.xxxxxxx.cc/web/validate/captcha.php?cid=134&3307 HTTP/1.0" 404 534 "-" "Trend Micro WTP Add-On 1.2.1046" TCP_MISS:FIRST_UP_PARENT 13

这里在处理URL用%1000是因为sscanf遇到空格就会停止,而url中可能会包含空格,所以直接算一个最大值,存下来就行,后面的类似。。

另外在网上搜到关于sscanf的详细说明,也不知道那个是原创了,也转贴在这里:

______________________________________________________________________________________

(转)sscanf() - 从一个字符串中读进与指定格式相符的数据

sscanf() - 从一个字符串中读进与指定格式相符的数据.

  函数原型:
  Int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
  int scanf( const char *format [,argument]... );

  说明:
  sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
  其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '/t' | '/n' | 非%符号}
  注:
  1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
  2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
  3、width表示读取宽度。
  4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
  5、type :这就很多了,就是%s,%d之类。
  6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值
  支持集合操作:
  %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
  %[aB'] 匹配a、B、'中一员,贪婪性
  %[^a] 匹配非a的任意字符,贪婪性
 
例子:
  1. 常见用法。
  char buf[512] = ;
  sscanf("123456 ", "%s", buf);
  printf("%s/n", buf);
  结果为:123456
  2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
  sscanf("123456 ", "%4s", buf);
  printf("%s/n", buf);
  结果为:1234
  3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
  sscanf("123456 abcdedf", "%[^ ]", buf);
  printf("%s/n", buf);
  结果为:123456
  4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
  sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
  printf("%s/n", buf);
  结果为:123456abcdedf
  5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
  sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
  printf("%s/n", buf);
  结果为:123456abcdedf
  6、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中
  sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
  printf("%s/n", buf);
  结果为:12DDWDFF
  7、给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
  sscanf(“hello, world”, "%*s%s", buf);
  printf("%s/n", buf);
  结果为:world
  %*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
  如果没有空格则结果为NULL。
  sscanf的功能很类似于正则表达式, 但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式.
  //-------------------------------------------------------
  sscanf,表示从字符串中格式化输入
  上面表示从str中,输入数字给x,就是32700
  久以前,我以为c没有自己的split string函数,后来我发现了sscanf;一直以来,我以为sscanf只能以空格来界定字符串,现在我发现我错了。
  sscanf是一个运行时函数,原形很简单:
  int sscanf(
  const char *buffer,
  const char *format [,
  argument ] ...
  );
  它强大的功能体现在对format的支持上。
  我以前用它来分隔类似这样的字符串2006:03:18:
  int a, b, c;
  sscanf("2006:03:18", "%d:%d:%d", a, b, c);
  以及2006:03:18 - 2006:04:18:
  char sztime1[16] = "", sztime2[16] = "";
  sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);
  但是后来,我需要处理2006:03:18-2006:04:18
  仅仅是取消了‘-’两边的空格,却打破了%s对字符串的界定。
  我需要重新设计一个函数来处理这样的情况?这并不复杂,但是,为了使所有的代码都有统一的风格,我需要改动很多地方,把已有的sscanf替换成我自己的分割函数。我以为我肯定需要这样做,并伴随着对sscanf的强烈不满而入睡;一觉醒来,发现其实不必。
  format-type中有%[]这样的type field。如果读取的字符串,不是以空格来分隔的话,就可以使用%[]。
  %[]类似于一个正则表达式。[a-z]表示读取a-z的所有字符,[^a-z]表示读取除a-z以外的所有字符。
  所以那个问题也就迎刃而解了:
  sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2);
  在softmse (Jake) 的问题贴http://community.csdn.net/Expert/topic/4843/4843294.xml?temp=. 4321558中 ,周星星给出了一个很cool的sscanf用例,而后通过学习,发现sscanf真棒,现做一总结。
  原问题:
  iios/12DDWDFF@122
  获取/和@之间的字符串怎么做
  C程序里面有什么函数吗?
  周星星的代码:
  #include <stdio.h>
  int main()
  {
  const char* s = "iios/12DDWDFF@122";
  char buf[20];
  sscanf( s, "%*[^/]/%[^@]", buf );
  printf( "%s/n", buf );
  return 0;
  }
  结果为:12DDWDFF
  sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
  函数原型:
  int scanf( const char *format [,argument]... );
  其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '/t' | '/n' | 非%符号},
  注:{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
  width:宽度,一般可以忽略,用法如:
  const char sourceStr[] = "hello, world";
  char buf[10] = ;
  sscanf(sourceStr, "%5s", buf); //%5s,只取5个字符
  cout << buf<< endl;
  结果为:hello
  {h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
  type :这就很多了,就是%s,%d之类。
  特别的:
  %*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值。如:
  const char sourceStr[] = "hello, world";
  char buf[10] = ;
  sscanf(sourceStr, "%*s%s", buf); //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
  cout << buf<< endl;
  结果为:world
  支持集合操作:
  %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
  %[aB'] 匹配a、B、'中一员,贪婪性
  %[^a] 匹配非a的任意字符,贪婪性
  是不是感觉眼熟了啊,不错,这和正则表达式很相似,而且仍然支持过滤,即可以有%*[a-z].如:
  星星大哥例子回顾:
  const char* s = "iios/12DDWDFF@122";
  char buf[20];
  sscanf( s, "%*[^/]/%[^@]", buf );
  printf( "%s/n", buf );
  由例子3-》取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
  sscanf("123456 abcdedf", "%[^ ]", buf);
  printf("%s/n", buf);
  结果为:123456
  所以周星星的代码总结应该为:
  const char* s = "iios/12DDWDFF@122";
  char buf[20];
  sscanf( s, "%*[^/]/%[^@]", buf );
  printf( "%s/n", buf );
  先将 "iios/"过滤掉,再将到字符'@'为止的一串12DDWDFF(由例3可得此串到@为止,把@122舍掉)内容即是:12DDWDFF送到buf中,得到结果。

sscanf 其实很强大相关推荐

  1. 计算机视觉,图像处理 经典代码paper整理(很全很强大!)

    转自:Jia-Bin Huang 同学收集了很多计算机视觉方面的代码 ,链接如下: https://netfiles.uiuc.edu/jbhuang1/www/resources/vision/in ...

  2. 【Python】用 Highcharts 绘制饼图,也很强大

    来源:Python数据之道 作者:Peter 整理:阳哥 用 Highcharts 绘制饼图,也很强大 前不久,分享了读者投稿的文章,较为综合的介绍了可视化库 Highcharts ,这个一个 Jav ...

  3. 肝!用 Highcharts 绘制饼图,也很强大

    来源 / Python数据之道 作者/Peter   整理/阳哥 用 Highcharts 绘制饼图,也很强大 前不久,分享了读者投稿的文章,较为综合的介绍了可视化库 Highcharts ,这个一个 ...

  4. 表单和字都居中_APP 分享 | 6 款黑科技工具,低调收藏,每一款都很强大!

    iSlide 简单.高效地制作PPT 使用环境:    Windows 使用要求:    Office 2010 及以上版本 授权状况:    无广告 有付费功能 官网地址:    www.islid ...

  5. sed很强大的文本操作命令

    sed对文本的处理很强大,并且sed非常小,参数少,容易掌握,他的操作方式根awk有点像.sed按顺序逐行读取文件.然后,它执行为 该行指定的所有操作,并在完成请求的修改之后的内容显示出来,也可以存放 ...

  6. java 跨平台很鸡肋,Mac 篇八:Mac上的这个软件看起来很鸡肋,其实很牛很强大

    Mac 篇八:Mac上的这个软件看起来很鸡肋,其实很牛很强大 2019-11-26 11:37:36 8点赞 42收藏 1评论 用了很多年Mac,可能这个应用都没有注意到,看起来不起眼,其实用好它,不 ...

  7. Chrome 浏览器书签功能很强大

       Chrome 浏览器书签功能很强大,书签功能其实就是收藏夹.点击扳手-书签-显示书签,即可在浏览器顶部显示书签.一个网站如果要加入书签,直接在点击浏览器地址栏右侧的五角星即可.    更强大的是 ...

  8. 群辉nas虚拟linux,UNRAID教程:3分钟 用unraid自带的虚拟机 安装 黑群晖NAS DSM系统 很强大!...

    UNRAID教程:3分钟 用unraid自带的虚拟机 安装 黑群晖NAS DSM系统 很强大! 2019-12-20 20:00:00 305点赞 879收藏 306评论 创作立场声明:不喜勿喷,谢谢 ...

  9. unraid虚拟linux系统,UNRAID教程:3分钟 用unraid自带的虚拟机 安装 黑群晖NAS DSM系统 很强大!...

    前言 大家好,俺又来了. 相信很多朋友,真的是久等了吧,这已经是我写的第四篇关于UNRAID的文章了. 这篇文章内容,是教给大家,如何用UNRAID自带的虚拟机来安装 一个群晖NAS系统. (本次文章 ...

最新文章

  1. 三层交换机与路由器的比较
  2. Linux下编译运行C程序
  3. 黑入苹果、特斯拉竟如此容易!这位鬼才的攻击方法火了!
  4. The Internet Communications Engine (Ice) 跨平台异构通讯方案 第一弹-ICE简介
  5. SIFT四部曲之——构建关键点特征描述符
  6. Java 定时任务调度(8)--ElasticJob 入门实战(ElasticJob-Lite使用)
  7. 功能接口简介–在Java 8中重新创建的概念
  8. 第六篇:如何学习C语言?
  9. 2010年寒假学习心得
  10. java借口案例实现_java实现接口的典型案例
  11. 光复用技术中三种重要技术_【技术文章】X射线无损检测仪在锂电池行业中的重要应用...
  12. 一步一步学Ruby(五): Class, Module, Object,Kernel的关系
  13. 如何下载海淀区卫星地图高清版大图
  14. 微信小程序获取数据并展示
  15. Ubuntu 图标主题 Nitrux 升级
  16. 域名抢注代码_如何停止域名抢注攻击
  17. 性别单选框jsp_jsp获取单选按钮的值源码实例
  18. 安卓短信软件_【安卓清理君】极度舒适的垃圾清理工具
  19. 注册时添加学号Idnumber
  20. 安卓高级 WebView的使用到 js交互

热门文章

  1. java类加载器—ContextClassLoader类加载器
  2. 【开发工具】史上最全的IDEA快捷键总结 MAC版
  3. 'BMap' is not defined 解决方案
  4. 面向对象编程和面向接口编程的区别
  5. ansys时间步长怎么设置_在 ANSYS Workbench 的动态、静态仿真中,设置子步长(时间步长)的目的分别是什么?_学小易找答案...
  6. 金仓数据库KingbaseES并行查询
  7. 【分享】vofa+串口调试助手
  8. 人工智能又攻下一城:从智能翻译机掀起的AI硬件销售热潮说起
  9. 4|无线传感器网络与应用|无线传感器网络原理及方法-许毅版|考试知识点
  10. LeetCode-Python-277. 搜寻名人