1

a = "/some/{tag}/here"2 つの文字列を考えると、変数 (つまり: ) で定義されたパターンに一致するかどうか、および一致b = "/some/text/here"するかどうかを検証する効率的なアルゴリズムが必要です。babtag = "text"

C や Go での実装も歓迎ですが、疑似コードでも問題ありません。

4

7 に答える 7

3

Knuth–Morris–Pratt 文字列検索アルゴリズムについて読んでください。疑似コードを含め、必要なものはすべて提供する必要があります。

于 2012-04-15T15:00:24.747 に答える
2

多くの優れた正規表現ツールキットでこれを行うことができますが、パターンの構文を変更する必要がある場合があります。たとえば、Python のバージョンは次のとおりです。

>>> import re
>>> a = re.compile("/some/(?P<pattern>.+)/here")
>>> b = "/some/text/here"
>>> a.match(b).group("pattern")
'text'
于 2012-04-15T15:00:31.107 に答える
2

たぶん、あなたは分割することができますa

string[] array1 = a.Split('/');
string[] array2 = a.Split('/');
bool isEqual = (array1[2] == array2[2]);
于 2012-04-15T15:02:34.413 に答える
1

したがって、フォームのパターン文字列があり、/some/{tag}/here他の文字列がそのパターンに一致するかどうかを判断する必要があります。もしそうなら、あなたはその{tag}部分を抽出したいと思います。

パターン文字列を3つの部分に分割できるようです。

"/some/"
"{tag}"
"/here"

ここで、標準のC比較関数(私はのようなものを考えています)を使用して、文字列がで始まり、で終わるstrncmpかどうかを確認します。含まれている場合は、タグ文字列の最初と最後を簡単に見つけることができます。始まりは:"/some/""/here"

stringBegin = s + strlen("/some/");
length = strlen(s) - strlen("/some/") - strlen("/here");

次に、その部分文字列をコピーするだけです。

もちろん、私の例は定数文字列を使用しています。ただし、コンポーネントを簡単に分割できる場合は、定数の代わりに変数を使用できます。

于 2012-04-15T18:36:36.703 に答える
1

Go の回答: Go 標準ライブラリには、役立つURL パーサー正規表現パッケージがあります。Go では実行時に変数に名前を付けることはできないため、答えを as として取得することtag = "text"はあまり意味がありません。代わりに、結果を構造体として返したり、複数の結果をマップに収集したりすることができます。アウトラインは次のようになります。

  1. タグ構文と中括弧を一致させる正規表現をコンパイルします。これは、プログラムのロード時に 1 回行います。これを tagRE と呼びましょう。
  2. パターン「a」にtagREを適用します。この一致の結果は、一致する URL の部分とタグの名前になります。(一致しない場合、パターン "a" は無効です。)
  3. 結果を使用して、実際の URL でそのパターンに一致する別の正規表現を構築およびコンパイルします。これをAREと呼びましょう。将来このパターンに一致させる必要があると思われる限り、この正規表現を保持してください。それをコンパイルする作業を繰り返しても意味がありません。
  4. 必要に応じて他のパターンに対して必要に応じて手順 2 と 3 を繰り返したり、パターンがプログラムで使用可能になったときに繰り返します。たぶん、これらをスライスやマップなどに集めます。これらを、一致が見つかったときに実行するコードなど、アプリケーションで役立つ何かに関連付けることも必要になると思います。
  5. 一致させたい実際の URL がある場合、まず URL パッケージを使用してそれを解析し、URL パスを分離することをお勧めします。
  6. パスに aRE (またはスライス内のすべての正規表現) を適用し、一致するかどうかを確認します。その場合、a からのタグ名と aRE が一致したパスの一部を含む結果を返します。これを行うには、結果構造体を作成するか、結果マップに追加します。

正規表現の構成を示すコード:

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 = パン
and = ジャム

于 2012-04-15T16:58:06.937 に答える
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");
}

2番目の風景:

パスターゲットの前身だけを知っていると仮定すると、次のようなことができます。

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解析から逃れることができます(もちろん、当然のことながら)。

これがお役に立てば幸いです。

于 2012-05-08T00:02:40.283 に答える
0

タグにスラッシュを含めることはできないと思います。そうでない場合、私のソリューションはかなりの変更なしでは機能しません。

ただし、上記が当てはまる場合は、最初にパスをリストにトークン化できます。私の解決策は行きます。

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 は、一致したものを変数に取り込むクロージャーになります。

于 2012-04-16T16:16:37.880 に答える