2017-05-06 113 views
1

我正在尝试使用正则表达式在React.js中编写一个简单的文本替换程序,但是我无法将其包围。使用正则表达式从列表中替换带有标记的标记

所以我有一个令牌列表及其相应的替换文本。我还有一个由用户编写文本的文本区域。每当一个单词缠绕{}时,文本将被替换为相应令牌的替换文本。

例如,如果我在textarea的某处有一个{example},我将不得不检查我的标记列表并查看列表中是否有值示例,并用列表的替换值的值替换{example} 。

我在做什么,现在是检查是否使用我有我的textarea的任何比赛:

let regEx = /\{[a-zA-Z_][a-zA-Z0-9_]*\}/; 
inputText.match(regEx); 

结果我发现了一个指数和投入,但我怎能取代匹配文字与替换文字?我尝试使用替换功能,但不知何故,我不明白如何使用它。

这里是我的过滤功能,为您检查出:

this.filterText =() => { 
    //check if we have text in Input text area 
    if (this.state.inputText) { 
    let regEx = /\{[a-zA-Z_][a-zA-Z0-9_]*\}/; 
    let inputText = this.state.inputText; 
    this.state.data.forEach((token, index) => { 
     let match = inputText.match(regEx); 
     if (match) { 
     console.log('match:', match); 
     //should replace matched text with replacement text 
     inputText.replace(regEx, this.state.data[index].replacementText); 
     } 
    }); 
    } 
} 

回答

1

下面是一个简单的香草js的解决方案。尝试例如键入我喜欢{make}东西 textarea中的任何位置。 {make}create

编辑已经做出

更改,以支持递归替换被替换。

现在可以在替换字符串中包含一些{token}

代码还可以防止循环调用。

尝试键入{hello}{circular}以确保其按照您想要的方式工作。

片段

document.addEventListener("DOMContentLoaded", function() { 
 
    buildResult(); 
 
}); 
 

 
let tokens = { 
 
    "civility": "Mr", 
 
    "dummy": "really dummy", 
 
    "foo": "bar", 
 
    "firstName": "Marty", 
 
    "lastName": "McFly", 
 
    "hello": "Hello {firstName} {lastName}", 
 
    "circular": "Hello {circular} {firstName} {lastName}", 
 
    "make": "create", 
 

 
} 
 

 
function buildResult() { 
 
    let text = document.getElementById('userInput').value; 
 
    let result = replaceTokens(text); 
 
    document.getElementById('result').innerHTML = result; 
 
} 
 

 
function replaceTokens(text, replacementStack) { 
 
    // const re = /{([^}]+)}/g; // match anything but a `}` between braces 
 
    const re = /{[\w]*\}/g; // match initial regex 
 

 
    let result = text; 
 
    let textTokens = text.match(re); 
 
    replacementStack = replacementStack || []; 
 

 
    textTokens && textTokens.forEach(m => { 
 
    let token = m.replace(/{|}/g, ''); 
 
    // Prevent circular replacement, token should not have already replaced 
 
    if (replacementStack.indexOf(token) === -1) { 
 
     // add token to replacement stack 
 
     replacementStack.push(token); 
 
     let replacement = tokens[token]; 
 
     if (replacement) { 
 
     replacement = replaceTokens(replacement, replacementStack); 
 
     result = result.replace(m, replacement); 
 
     } 
 
    } 
 
    }); 
 

 
    return result; 
 
}
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <title></title> 
 
    <script src="script.js"></script> 
 
    <style> 
 
    label { display: block; font-weight: bold; } 
 
    textarea { width: 600px; height: 150px; } 
 
    </style> 
 
</head> 
 
<body> 
 

 
    <label>Enter text</label> 
 
    <textarea id="userInput" onkeyup="buildResult()">Lorem Ipsum is simply {dummy} text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to {make} a type specimen book. 
 
It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</textarea> 
 

 
    <label>Result</label> 
 
    <div id="result"></div> 
 

 
</body> 
 
</html>

+0

我喜欢你的解决方案,有一些调整,我可以让我自己的例子工作。我有一个问题,但我的正则表达式与你的有什么区别?使这个例子也能递归地工作会难吗?如果我在替换文本中有{test},那么我将再次解析它,并检查测试是否在令牌列表中并将其替换为文本。谢谢 – captain

+0

完成!我认为它涵盖了你的需求。 –

+0

关于你的正则表达式,我只是在大括号之间匹配任何东西,但是如果你只需要匹配字母,数字或下划线,那么你可以像这样简化你:'{[\ w] * \}'。 '\ w'匹配任何字母,数字或下划线。相当于[a-zA-Z0-9_]。大括号不需要被转义。 –

0

它不工作,因为里面的正则表达式替换功能必须是你试图取代(令牌本身在这种情况下)到底是什么。

试试这个: https://jsfiddle.net/KlaussU/f4mxa3vw/2/

<button onclick="replaceText('tokenX replaced: {tokenX}')">Try it</button> 
<p id="demo"></p> 

<script> 
var replacementText = { 
    "tokenX": "tokenXReplaced", 
    "tokenY": "tokenYReplaced", 
    "tokenZ": "tokenZReplaced" 
}; 

function replaceText(text) { 
    for(var rt in replacementText) { 
     text = text.replace(new RegExp("{" + rt + "}"), replacementText[rt]); 
    } 
    document.getElementById("demo").innerHTML = text; 
} 
</script> 

P.S你可能会在这里找到接受的答案也非常有用: Javascript Regex: How to put a variable inside a regular expression?

0

你永远不会发布的代码将replace的结果。我不确定data结构,但下面的内容应该与布局有些相符。

function foo(){ 
 
\t this.state = {inputText:'this is a test that should {verb} both the first {noun} between {} and also the following {noun}s, but not {other} tags'}; 
 
    this.data = {verb:'replace', noun:'element'}; 
 
    this.filterText =() => !this.state.inputText || Object.keys(this.data).reduce((t,k)=> 
 
    \t t.replace(new RegExp('{' + k + '}','g'),this.data[k]) 
 
    \t ,this.state.inputText 
 
); 
 
} 
 

 
let f = new foo();console.log(f.filterText());

的想法是翻领的逻辑,而不是找到所有{}标签,但使用令牌作为源(这是一样的Klaus的答案,我现在看到的) 。 在这里甚至不需要正则表达式替换,但它是为g lobal国旗