检测输入多少单词的算法,也支持多句支持(Java)

时间:2010-04-30 13:22:04

标签: java algorithm

问题:

我必须设计一个算法,它为我做了以下事情:

说我有一条线(例如)

alert tcp 192.168.1.1 (caret is currently here)

算法应处理此行,并返回值4。

我为它编写了一些东西,我知道它很邋,,但它的确有效。

private int counter = 0;
    public void determineRuleActionRegion(String str, int index) {
        if (str.length() == 0 || str.indexOf(" ") == -1) {
            triggerSuggestionList(1);
            return;
        }

        //remove duplicate space, spaces in front and back before searching
        int num = str.trim().replaceAll(" +", " ").indexOf(" ", index);
        //Check for occurances of spaces, recursively
        if (num == -1) { //if there is no space
            //no need to check if it's 0 times it will assign to 1
            triggerSuggestionList(counter + 1);
            counter = 0;
            return; //set to rule action
        } else { //there is a space
            counter++;
            determineRuleActionRegion(str, num + 1);
        }

    } //end of determineactionRegion()

所以基本上我找到空间并确定区域(键入的单词数)。但是,我希望在用户按空格键<space character>时更改。

我如何使用当前代码?

或者更好的是,如何建议我以正确的方式执行?我正在为这个案子搞清楚BreakIterator ......

除此之外,我相信我的算法不适用于多句话我应该如何处理这个问题。

-

String str的源代码来自textPane.getText(0, pos + 1);,即JTextPane。

提前致谢。如果我的问题仍然不够具体,请告诉我。

-

更多例子:

alert tcp $EXTERNAL_NET any -> $HOME_NET 22 <caret>

返回-1(键入的文本的最大值为7个单词)

alert tcp 192.168.1.1 any<caret> 

返回4(因为它仍处于第2个arg)

alert tcp<caret>

返回2(因为它仍处于第二个arg)

alert tcp <caret>

返回3

alert tcp $EXTERNAL_NET any -> <caret>

返回6

它类似于shell命令。如上。虽然我认为它并没有多大差别我相信,但我只是想知道输入了多少个参数。感谢。

-

伪代码

Get whole paragraph from textpane
  if more than 1 line -> process the last line
      count how many arguments typed and return appropriate number
  else
    process current line
      count how many arguments typed and return appropriate number
End

4 个答案:

答案 0 :(得分:3)

这使用String.split;我想这就是你想要的。

    String[] texts = {
        "alert tcp $EXTERNAL_NET any -> $HOME_NET 22 ",
        "alert tcp 192.168.1.1 any",
        "alert tcp",
        "alert tcp ",
        "alert tcp $EXTERNAL_NET any -> ",
        "multine\ntest\ntest  1   2   3",
    };

    for (String text : texts) {
        String[] lines = text.split("\r?\n|\r");
        String lastLine = lines[lines.length - 1];

        String[] tokens = lastLine.split("\\s+", -1);
        for (String token : tokens) {
            System.out.print("[" + token + "]");
        }

        int pos = (tokens.length <= 7) ? tokens.length : -1;
        System.out.println(" = " + pos);
    }

这会产生以下输出:

[alert][tcp][$EXTERNAL_NET][any][->][$HOME_NET][22][] = -1
[alert][tcp][192.168.1.1][any] = 4
[alert][tcp] = 2
[alert][tcp][] = 3
[alert][tcp][$EXTERNAL_NET][any][->][] = 6
[test][1][2][3] = 4

答案 1 :(得分:1)

这个怎么样:得到最后一行,计算空格之间的内容......

String text = ...
String[] lines = text.split("\n"); // or \r\n depending on how you get the string
String lastLine = lines[lines.length-1];
StringTokenizer tokenizer = new StringTokenizer(lastLine, " ");
// note that strtokenizer will ignore empty tokens, it is, what is between two consecutive spaces
int count = 0;
while (tokenizer.hasMoreTokens()) {
  tokenizer.nextToken();
  count++;
}
return count;

编辑你可以控制你是否有一个最后的空格(lastLine.endsWith(“”))所以你开始一个新词或者其他什么,这是你完成它的基本方法: )

答案 2 :(得分:1)

polygenelubricants和helios提供的代码在一定程度上起作用。它解决了我所说的上述问题,但不涉及多行。 helios的代码更直接。

但是当你在JTextPane中输入时,两个代码都没有解决问题,它仍然会返回旧计数而不是1,因为split()将它作为一个句子而不是两个返回。

E.g。 alert tcp <enter is pressed> 右边它应该返回1,因为它是一个新句子。两个算法都返回2。 此外,如果我突出显示全部并删除两个算法将抛出NullPointerException,因为没有要拆分的字符串。

我添加了一行,它解决了上面提到的问题:

public void determineRuleActionRegion(String str) {
    //remove repetitive spaces and concat $ for new line indicator
    str = str.trim().replaceAll(" +", " ") + "$";
    String[] lines = str.split("\r?\n|\r");
    String lastLine = lines[lines.length - 1];
    String[] tokens = lastLine.split("\\s+", -1);
    int pos = (tokens.length <= 7) ? tokens.length : -1;
    triggerSuggestionList(pos);
    System.out.println("Current pos: " + pos);
    return;
} //end of determineactionRegion()

这样,当split()解析str时,"$"将创建另一行,无论如何都是最后一行,现在计数将返回到一行。此外,由于NullPointerException始终存在,因此不会"$"

但是,如果没有多基因润滑剂和helios的帮助,我认为我不会这么快就弄明白。谢谢你们!

编辑:好的......显然split("\r?\n|\r",-1)的工作原理相同。问题是我应该接受polygenelubricants还是我自己? HMM。

第二次编辑:将'%'连接到str的结尾有一点不好,lastLine.endsWith(" ") == true将返回false。因此,必须使用split("\r?\n|\r",-1)lastLine.endsWith(" ") == true来获得完整的解决方案。

答案 3 :(得分:0)

样品线是代表性的吗?一些基于规则的语言(ACL)的编辑器?

如何获得完整的信息提取/命名实体识别解决方案,能够识别实体(关键字,IP地址等)?您不必从头开始编写所有内容,而是现有的工具和库。

更新:我认为这是解析的piece of Snort code

Function ParseRule()
if (*args == '(') {
   // "Preprocessor Rule detected"

} else {
    /* proto ip port dir ip port r*/
    toks = mSplit(args, " \t", 7, &num_toks, '\\');

    /* A rule might not have rule options */
    if (num_toks < 6) {
        ParseError("Bad rule in rules file: %s", args);
    }
..
 }
 otn = ParseRuleOptions(sc, rtn, roptions, rule_type, protocol);
..

mSplit在mstring.c中定义,这是一个将字符串拆分为标记的函数。

在你的情况下,ParseRuleOptions应该为括号内的整个字符串返回一个。

更新2 :顺便说一下,你的第一个例子是正确的,因为在snort中,你可以为规则添加选项吗?例如,这是一个有效的规则(选项部分未完成):

alert tcp any any -> 192.168.1.0/24 111 (content:"|00 01 86 a5|"; <caret>

在某些情况下,你可以有6个或7个'单词',所以你的算法应该有更多的知识,对吗?