2017-09-18 7 views
1

テンプレートのリテラル内ですべての出現を<% anything %>と一致させようとしています。 正規表現の設定は次のようになります。私のテンプレートは、このRegexがすべての発生と一致していません

`<div class="tile"> 
     <span><%ENTRY_NUMBER%></span> 
     <span><%NAME%> , <%CLASS%> , <%GENDER%> , <%AGE%></span> 
</div>` 

のように見える場合

process(template : string , data: Object) { 
    let re = /<%([^%>]+)?%>/g, match; 
    while (match = re.exec(template)) { 
     template = template.replace(match[0], data[match[1]]); 
    } 
    return template; 
} 

それはその後、別の出現を選んでおくだけで罰金最初の出現と一致します。 htmlタグ内に1つのマッチがある場合はうまく動作しますが、2番目のspan要素のような倍数を使用すると、別のオカレンスが欠けてしまいます。私はそれが<と>と関係があると思います。

以下のようにコンマの代わりに<>でこれらのオカレンスを区切っても問題ありません。

<span><%NAME%> <> <%CLASS%> <> <%GENDER%> <> <%AGE%></span> 

結果、この

<span> john <> biology <> male <> 17 </span> 

ように私は正規表現を複数回調べたが、無駄にしています。

+1

はあなた 'しばらく交換してみてください'return template.replace(re、function($ 0、$ 1){return data [$ 1]?data [$ 1]:$ 0;})'でブロックします。また、ここで正規表現として 'let re =/<%(.+?)%>/g'を使用します(データキーに'> 'や'% 'がある場合のみ)。 –

+0

ご協力ありがとうございますが、私は説明を探しています**なぜ**私のコードは動作しません。また、私はjsで$とvar名を見たことがない。 –

+0

JavaScriptは、名前に '$'と '_'を使用するときに文字として扱います。彼らにとって特別なことは何もありません。どちらもJavaScriptコードではかなり一般的です:jQueryコードでは '$'、アンダースコア/ Lodashコードでは '_'です。 –

答えて

2

問題は、re.lastIndextemplateの前の値の正しいではありませんが、あなたはtemplate値を変更するのでre.lastIndexが変更された文字列のために、もはや正しい値。 、

let template = `<%ENTRY_NUMBER%><%NAME%><%CLASS%><%GENDER%><%AGE%>`; 
 
let re = /<%(.+?)%>/g, match; 
 
let data = { 'NAME':'John', 'CLASS':'A3', 'GENDER':'Male', 'AGE':'19' }; 
 
while (match = re.exec(template)) { 
 
    console.log(re.lastIndex); 
 
    template = template.replace(match[0], data[match[1]]); 
 
    console.log(template); 
 
} 
 
console.log(template); 
 

 
// Iteration 1: re.lastIndex = 16 
 
// undefined<%NAME%><%CLASS%><%GENDER%><%AGE%> 
 
// Index is now between <%NAME% and > -> this match will be skipped 
 
// and so on...

したがって、彼らが発見されたら、すべての一致が置き換えられてしまいますので、交換するコールバックの内側にその場で文字列を変更した方がよい:

は、以下の簡単な例を参照してください。検索する場所のインデックスをトラッキングする必要はありません。

使用

process(template : string , data: Object) { 
    return template.replace(/<%(.+?)%>/g, function($0, $1) { 
       return data[$1] ? data[$1] : $0; 
      }); 
} 

<%(.+?)%>試合<%こと、そしてできるだけ少ないとしてグループ1に、改行文字以外の任意の1つの以上の文字をキャプチャして、%>と一致します。このようにして、%>を含む値も一致させます(dataにそのようなキーが含まれている場合は重要です)。

+0

彼のアプローチの問題は、あなたが強調した 'lastIndex'問題を引き起こす' g'フラグです。代わりに 'm'フラグを使うと、彼のアプローチはうまく動作します。そして、ええ、コールバックの置き換えはよりエレガントです:) – bluehipy

+0

はい、私は既に 're.lastIndex'が各マッチ時に変更されたと述べました。 Look:[*正規表現が "g"フラグを使用する場合、 'exec()'メソッドを複数回使用して、同じ文字列内の連続する一致を見つけることができます。そうすると、正規表現のlastIndexプロパティで指定された 'str'の部分文字列から検索が始まります(' test() 'も' lastIndex'プロパティを進めるでしょう)*](https://developer.mozilla。 org/ja-jp/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec)を参照してください。 'm'フラグはここで完全に冗長です。 –

+0

最初のソースからgフラグを削除するだけで問題は解決されます。 – bluehipy

0

問題が一致しなくなるまで、何度も繰り返し表現を再実行becuaseあなたはグローバルフラグgを必要としないですが、複数行フラグm

let s = `<div class="tile"> 
 
     <span><%ENTRY_NUMBER%></span> 
 
     <span><%NAME%> , <%CLASS%> , <%GENDER%> , <%AGE%></span> 
 
</div>`; 
 
const re = /<%([^\%]+)?%>/, 
 
    data = { 
 
    ENTRY_NUMBER: '1977', 
 
    NAME: 'Blue', 
 
    CLASS: 'Vertebrates', 
 
    GENDER: 'Male', 
 
    AGE: '40' 
 
    }; 
 

 

 
let k = 0; 
 
while (re.test(s) && k++ < 1000) { 
 
    match = re.exec(s); 
 
    if (match) s = s.replace(match[0], data[match[1]]); 
 
} 
 
console.log(s);

+0

'm'修飾子は何をしていますか?ヒント:パターンから削除すると、結果は同じになります。 '<'、 '%'、 '>'は特別な正規表現のメタキャラクタではなく、エスケープする必要はないことをご存知ですか? –

+0

あなたは正しいです、ありがとう! – bluehipy

関連する問題