sscanf 其实很强大

分类: 纯C技术 技术笔记 2010-03-05 16:00 12133人阅读 评论(4) 收藏 举报

正则表达式stringbuffercurlgoogle

最近在做日志分析,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 函数 分类: POJ 2015-08-04 09:19 4人阅读 评论(0) 收藏的更多相关文章

  1. Transact-SQL 常用函数 分类: SQL Server 2015-02-03 09:47 284人阅读 评论(0) 收藏

    (1)DECLARE 两种用法: 1>: DECLARE @usid VARCHAR(50),@usna NVARCHAR(100),@grna NVARCHAR(100); 2>: DE ...

  2. Jquery easy UI 上中下三栏布局 分类: ASP.NET 2015-02-06 09:19 368人阅读 评论(0) 收藏

    效果图: 源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  3. Poj 2528 Mayor's posters 分类: Brush Mode 2014-07-23 09:12 84人阅读 评论(0) 收藏

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 40570   Accepted: 11798 ...

  4. 哈希-4 Values whose Sum is 0 分类: POJ 哈希 2015-08-07 09:51 3人阅读 评论(0) 收藏

    4 Values whose Sum is 0 Time Limit: 15000MS Memory Limit: 228000K Total Submissions: 17875 Accepted: ...

  5. Poj 2349 Arctic Network 分类: Brush Mode 2014-07-20 09:31 93人阅读 评论(0) 收藏

    Arctic Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9557   Accepted: 3187 De ...

  6. Poj 1050 分类: Translation Mode 2014-04-04 09:31 103人阅读 评论(0) 收藏

    To the Max Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39058   Accepted: 20629 Desc ...

  7. Babelfish 分类: 哈希 2015-08-04 09:25 2人阅读 评论(0) 收藏

    Babelfish Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 36398 Accepted: 15554 Descripti ...

  8. Hdu 1507 Uncle Tom's Inherited Land* 分类: Brush Mode 2014-07-30 09:28 112人阅读 评论(0) 收藏

    Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  9. Ubuntu vim+ ctags(包含系统函数) + taglist 配置 分类: vim ubuntu 2015-06-09 18:19 195人阅读 评论(0) 收藏

    阅读大型代码,我们经常需要打开很多的代码文件,搜索各种定义.windows下用惯了ide的朋友,转战Linux的时候可能会觉得很难受,找不到合适的阅读工具.其实万能的vim就可以实现.下面介绍一下vi ...

随机推荐

  1. Java FX中TreeView节点选中和双击事件监听

    TreeItem<String> treeRoot = new TreeItem<String>("Root"); treeRoot.setExpanded ...

  2. 如何抠PSD素材中的图片

    在网上经常可以找到一些好看呢的PSD素材,如何才能将这些素材抠出来 存成一张张的png图片呢? 在PhotoShop中 1·隐藏无用的图层,然后窗口中仅剩需要看到的那个素材图 2·用工具选择该区域(注 ...

  3. Open quote is expected for attribute "property" associated with an element type "result".错误

    java  Mybatis 框架下的项目 报   Open quote is expected for attribute "property" associated with a ...

  4. js中把JSON字符串转换成JSON对象最好的方法

    在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 第一种解析方式:使用eval函数来解析,并且使用j ...

  5. Inside TSQL Querying - Chapter 3. Query Tuning

    Tuning Methodology When dealing with performance problems, database professionals tend to focus on t ...

  6. 一个容易被忽略的ReportingService超时问题

    我们在使用Sql Server Reporting Service开发报表的时候,经常会遇到报表超时的问题,报表超时的原因有很多,也有很多地方可以设置报表的超时时间,比如在报表中的数据源(dataso ...

  7. SVN使用(二)

    TortoiseSVN是windows平台下Subversion的免费开源客户端. 一般我们都是先讲讲服务器的配置,然后再讲客户端的使用,但是在TortoiseSVN上,却可以反过来.因为,如果你的要 ...

  8. 鸟哥的linux私房菜学习记录之开机流程、模块管理与Loader

  9. Servlet概念框架

    以 Servlet 3.0 源代码为基础.Servlet 是 Javaweb 应用的基础框架,犹如孙子兵法之于作战指挥官,不可不知. 概念框架 机制: 事件 Event, 监听器 Listener 数 ...

  10. javaWeb---Servlet

    1.整个Servlet页面跳转访问流程: 1.1:依据form表单的action的值找到web.xml中servlet-mapping的url的值找到对应的java类,在根据form中的method属 ...