跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

ABNF 模式字符串匹配

张 磊 (raphaelzl@263.net), 软件工程师, 银河网络公司
张磊,现在是银河网络公司的一个软件工程师,近一段时间主要开发的是基于Java的网络通信程序,其中包括文件传输和实时消息传输。在此之前是清华大学电子工程系的学生,主要方向是TCP/IP网络原理和程序编制,还有数字信号变换。

简介: ABNF 是 RFC2234 里面定义的一个字符串模式匹配的文法定义 (syntax),这个 syntax 在 RFC 的文档里面被广泛的引用,由此可见重要性,另外在实际的工作中间我们时常需要对表达式进行分析和模式匹配,本文给出一个 ABNF 字符串匹配的程序。

发布日期: 2001 年 4 月 12 日
级别: 初级
访问情况 : 908 次浏览
评论: 


ZSubSelector 的 interface,用来封装 Optional, Concatational 等 Rules 的接口

public interface ZSubSelector{ 
 String parseNext(String s, int index); 
 String parseCurrent(String s, int index); 
 String getCurrentPattern(); 
 boolean needEatBack(); 
 boolean hasNext() ; 
 void reset(); 
 int getOperator() ; 
 }


ZMalFormedBNFException 异常

public class ZMalFormedBNFException extends Exception{ 
 public ZMalFormedBNFException(String s){ 
  System.out.println("[ZMalFormedBNFException] " + s); 
 } 
 public ZMalFormedBNFException(int type){ 
  System.out.println("[ZMalFormedBNFException] " + String.valueOf((char)type)); 
 } 
 }


增强性的 ZEnhancedSelector 的接口,给外面调用提供的

import java.util.*; 
 public interface ZEnhancedSelector extends ZSubSelector{ 
 List parseNext2(String s, int index); 
 List parseCurrent2(String s, int index); 
 void next(); 
 }


实现 ABNF 分析的核心代码和类工厂

源码清单


外部调用使用的类

源码清单


一个简单的例子程序

import java.util.*; 
static String namel; 
public class HttpSession{ 
    public static void main(String[] args)throws Exception{ 
        String templ = "\"name=\" 1*16(OCTET) \" \" 1*32(OCTET) " +
            "\"type=\" 1*16(OCTET) (\" \" / \">\")";
        System.out.println(templ); 
        ZBNFSelector selector = new ZBNFSelector(templ); 
        String s = "<input name=pass size=12 type=password " +
            "maxlength=\"8\" class=\"form1\">"; 
        System.out.println(s); 
        Iterator it = selector.select2(s); 
        while(it.hasNext()){ 
            List lst = (List)it.next(); 
            System.out.println("$" + (String)lst.get(1) + "$" + 
                (String)lst.get(5) + "$"); 
        } 
 } 


简单说明

ABNF 是 RFC2234 里面定义的一个字符串模式匹配的文法定义 (syntax),这个 syntax 在 RFC 的文档里面被广泛的引用,由此可见重要性,另外在实际的工作中间我们时常需要对表达式进行分析和模式匹配,所以我编了一个 ABNF 字符串匹配的程序 ..;)

我实现的 ABNF 和真正的 RFC2234 的 ABNF 模式不太一样,RFC2234 里面:字符串的顺序模式 (Concatational Rules,在正则表达式里面叫 Sequential Pattern 吧 ) 定义为 :element1 element2 element3 这样的形式,中间用 LWS(Linear White Space,就是 Tab 与空格的组合 ) 隔开 , 我的定义多了一个分组符号 (Gruping Rules):(element1 element2 element3) 一个字符串只有按顺序匹配了 element1 element2 element3 才是匹配了这个顺序模式

备选模式 (Optional Rules): element1 / element2 / element3

我也加了分组符号: (element1 / element2 / element3)

不过在 RFC2234 里面虽然备选模式没有分组符号,但是它强力推荐使用,这样使文法更加清晰而没有二义性一个字符串只要匹配了 element1, element2 或 element3 中间的任何一个就算匹配了这个备选模式

字符串 (Strings):"element"这个和我的一样,也适用双引号"来标志一个完整的字符串

重复模式 (Repetition):<m>*<n>element

为了清晰起见我改成了:m*n(element) 原来 RFC2234 里面还有省略形式的重复模式的,我把他们去掉了

范围选择模式 (Value range):m-n

省略号 (Comment):; element 这个我没有,不过要加应该也不难

在程序里面我定义了 ZConcatSelector 对应顺序模式,ZAlterSelector 对应备选模式,ZQuoteSelector 对应字符串模式,ZRepetSelector 对应重复模式,ZRangeSelector 对应范围选择模式

它们都继承了 ZSubSelector 这个接口,而由于最高一层的接口需要单独提出来,我特地定义了一个 ZEnhancedSelector 接口,在程序里面只有 ZConcatSelector 实现了这个接口

在 ABNF 分析的核心代码里面有一个 Factory Pattern 的应用,由于模版可以嵌套,整个 BNF 表达式是一个 Composite Pattern. 所以每个模版都可能有子模版,子模版的生成是由一个 Factory 统一产生的,每次需要产生子模版的时候就会调用 ZSubSelectorFactory 的 getSubSelector 方法得到一个子模版,这个工厂封装了生成各种模版的不同的参数和方法,这样每个模版都只知道工厂而对其他模版的生成细节不了解,程序的可维护性和扩展性比较好

在 ZSubsSelector 的 interface 里面有 parseNext 方法,实际上这个方法就暗示了 Composite Pattern 的存在,一个非叶节点的模版会调用每个子模版的 parseNext 方法得到匹配的字符串,每个叶结点如 ZQuoteSelector 直接比较内部的数据返回比较值

为了能得到一个用户制定模版里面的每个域的长度,在 ZEnhancedSelector 接口里面定义了新的方法 parseNext2 返回的是一个 List,里面是对应用户各个域的匹配出的字符串,免得用户进行第二次处理用户使用的 class 最后是 ZBNFSelector,这个类相对简单,用户传进去一个 BNF 表达式作为匹配的模版,然后调用 select 返回多个匹配的字符串或者调用 select2 返回一个迭代器,迭代器里每个元素是一个 List,让用户可以直接得到每个域的匹配字符串


关于作者

张磊,现在是银河网络公司的一个软件工程师,近一段时间主要开发的是基于Java的网络通信程序,其中包括文件传输和实时消息传输。在此之前是清华大学电子工程系的学生,主要方向是TCP/IP网络原理和程序编制,还有数字信号变换。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=52868
ArticleTitle=ABNF 模式字符串匹配
publish-date=04122001
author1-email=raphaelzl@263.net
author1-email-cc=raphaelzl@263.net

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。