鉴于两个字符串a = "/some/{tag}/here"
和b = "/some/text/here"
,我想要一个有效的算法来验证b
是否与a
定义的模式匹配,以及它是否提取相应的变量中b
的一部分(即:tag = "text"
)。
C或Go中的实现也很受欢迎,但伪代码也可以。
答案 0 :(得分:3)
了解the Knuth–Morris–Pratt string searching algorithm。应该为您提供所需的一切,包括伪代码。
答案 1 :(得分:2)
许多优秀的正则表达式工具包都可以做到这一点,但您可能需要更改模式的语法。例如,这是Python版本:
>>> import re
>>> a = re.compile("/some/(?P<pattern>.+)/here")
>>> b = "/some/text/here"
>>> a.match(b).group("pattern")
'text'
答案 2 :(得分:2)
也许你可以分开a
string[] array1 = a.Split('/');
string[] array2 = a.Split('/');
bool isEqual = (array1[2] == array2[2]);
答案 3 :(得分:1)
回答:Go标准库有一个URL parser和regular expression包来帮助您。 Go不允许您在运行时命名变量,因此将答案设为tag = "text"
并不合理。相反,您可能希望将结果作为结构返回,或者可能在地图中收集多个结果。大纲可能会像,
显示正则表达式构造的代码:
package main
import (
"fmt"
"regexp"
)
var a = "/some/{tag}/here/{and}/there"
var aPath = `/some/bread/here/jam/there`
func main() {
tagPat := regexp.MustCompile("([^{]*){([^}]+)}")
aMatch := tagPat.FindAllStringSubmatch(a, -1)
if aMatch == nil {
fmt.Println("bad pattern")
return
}
aRE := ""
matchLen := 0
for _, m := range aMatch {
if m[1] > "" {
aRE += `\Q` + m[1] + `\E`
}
aRE += "(?P<" + m[2] + ">.*)"
matchLen += len(m[0])
}
if matchLen < len(a) {
aRE += `\Q` + a[matchLen:] + `\E`
}
aPat := regexp.MustCompile(aRE)
pathMatch := aPat.FindStringSubmatch(aPath)
if pathMatch == nil {
fmt.Println("url doesn't match")
return
}
for tx, tag := range aPat.SubexpNames()[1:] {
fmt.Println(tag, "=", pathMatch[tx+1])
}
}
输出:
tag =面包
和=果酱
答案 4 :(得分:1)
因此,您有一个/some/{tag}/here
形式的模式字符串,并且您想确定某个其他字符串是否与该模式匹配。如果是,那么您想要提取{tag}
部分。
在我看来,您可以将模式字符串分成三个部分:
"/some/"
"{tag}"
"/here"
现在,使用标准C比较函数(我想的是strncmp
),检查字符串是以"/some/"
开头还是以"/here"
结尾。如果是,则可以轻松找到标记字符串的开头和结尾。开头是:
stringBegin = s + strlen("/some/");
length = strlen(s) - strlen("/some/") - strlen("/here");
然后复制掉子字符串很简单。
当然我的例子是使用常量字符串。但是,如果您可以轻松地拆分组件,那么您可以用变量替换常量。
答案 5 :(得分:0)
我假设你的标签不能包含斜杠。如果不是这样,那么我的解决方案就行不通 相当大的修改。
如果以上情况适用,那么您可以先将您的路径标记为一个列表,例如user1288160在他的回答中显示。我的解决方案将继续。
path := strings.Split(url, "/")
然后您可以使用简单的状态机来处理令牌。
type urlParser func([]string) (urlParser, []string, error)
// define handlers for the various tokens that do appropriate things
var parseMap map[string]urlParser
var startParse = func(ps []string) (urlParser, []string, error) {
switch {
case len(ps) == 0:
return nil, nil, errors.New("End Of Path")
case len(ps) == 1:
return parseMap[ps[0]], nil, nil
case len(ps) > 1:
return parseMap[ps[0]], ps[1:], nil
}
}
p := startParse
var err error
for {
// get the next step in the state machine, unparsed portion of the path
// and any errors.
next, rst, pErr := p(path)
// an error means we are done.
if pErr != nil {
break;
}
// set up for our next iteration of the parse loop.
p = next
path = rst
err = pErr
}
你的urlParsers将是一个闭包,用你匹配的任何东西填充一些变量。
答案 6 :(得分:0)
我们可以帮助它,我们需要背景信息。例如,构成“模式”的是什么,数字?信吗?数字和字母?允许哪些字符?
第一个场景:假设路径目标的位置是固定的,你可以这样做:
C代码:
char * string = "/some/text/here";
char * path;
char * b = "text";
if(strtok(strdup(string), "/")) {
path = strtok(NULL, "/");
if(!strcmp(b, path)) {
/* Are equals. Do something.. */
} else {
/* ... */
}
} else {
printf("Not found tag.\n");
}
第二个风景:
假设你只知道路径目标的前身,你可以这样做:
C代码:
char * string = "/some/text/here";
char *cpath, /* Current path */
*ppath = NULL, /* Predecessor path */
*ptpath = "some", /* Predecessor path target */
*pathcmp = "text"; /* Path to compare */
cpath = strtok(strdup(string), "/");
while(cpath) {
ppath = cpath;
cpath = strtok(NULL, "/");
if(ppath && ptpath && !strcmp(ppath, ptpath)) {
if(!strcmp(cpath, pathcmp)) {
/* Are equals. */
} else {
/* ... */
}
break;
}
}
这样的非常简单的案例,可以从正则表达式和URI解析中逃脱(当然,在很好的意义上)。
我希望这对你有所帮助。