通过正则表达式删除和替换字符

时间:2015-02-07 14:08:33

标签: javascript regex

我正在尝试编写一个正则表达式来完成下一步:

  1. _ - >用空格替换
  2. + - >如果之后没有其他+,则删除它(即c++ => c++c+ - > c
  3. ' - >如果它在单词的开头或结尾(即 Alin's - > Alin's'Alin's - > alin's
  4. &-.! - 请勿删除。
  5. 另一个特殊字符 - 删除
  6. 我想通过传递一次字符串

    来做到这一点

    例如:

    Input: "abc's, test_s! & c++ c+ 'Dirty's'. and beautiful'..."
    Output: "abc's test s! & c++ c Dirty's. and beautiful..."
    

    说明:

    char `'` in `abc's,` stays because `3`
    char `,` in `abc's,` was removed because `5` 
    char `_` in `test_s!` was replaced by space because `1`
    char `!` in `test_s!` is not removed because `!`
    char `&` is not removed because `4`
    char `+` in `c++` is not removed because `2`
    char `+` in `c+` was removed because `2`
    word: `'Dirty's'.` was replaced to `Dirty's.` because `3` and `4`
    char `'` in `beautiful'...` was removed because `3`
    char `.` is not removed because of `4`
    

    这是我的javascript代码:

    var str = "abc's test_s c++ c+ 'Dirty's'. and beautiful";
    console.log(str);
    str = str.replace(/[_]/g, " ");
    str = str.replace(/[^a-zA-Z0-9 &-.!]/g, "");
    console.log(str);
    

    这是我的jsfiddle:http://jsfiddle.net/alonshmiel/LKjYd/4/

    我不喜欢我的代码,因为我确信可以通过在字符串上运行一次来​​实现它。

    任何帮助表示赞赏!

4 个答案:

答案 0 :(得分:3)



function sanitize(str){

  return str.replace(/(_)|(\'\W|\'$)|(^\'|\W\')|(\+\+)|([a-zA-Z0-9\ \&\-\.\!\'])|(.)/g,function(car,p1,p2,p3,p4,p5,p6){

   if(p1) return " "; 
   if(p2) return sanitize(p2.slice(1));
   if(p3) return sanitize(p3.slice(0,-1)); 
   if(p4) return p4.slice(0,p4.length-p4.length%2); 
   if(p5) return car;
   if(p6) return ""; 
 });
}
document.querySelector('#sanitize').addEventListener('click',function(){
  
  document.querySelector('#output').innerHTML=      
	  sanitize(document.querySelector('#inputString').value);
});

#inputString{
  width:290px
}
#sanitize{
  background: #009afd;
  border: 1px solid #1777b7;
  border:none;
  color:#fff;
  cursor:pointer;
  height: 1.55em;
}

#output{
  background:#ddd;
  margin-top:5px;
  width:295px;
}

<input id="inputString" type="text" value="abc's test_s! & c++ c+ 'Dirty's'. and beau)'(tiful'..."/>
<input id="sanitize" type="button" value="Sanitize it!"" />
<div id="output" ></div>
&#13;
&#13;
&#13;

一些观点:

  • 由于有义务清理用\ W捕获的角色,因此没有完全遵守一次通过限制。我没有找到任何其他方式。
  • 关于++规则:如果受到损害,任何+的序列都减少一个+。
  • 只有在旁边有非字母数字字符时才会删除
  • 撇号。你应该怎么做,例如:&#34; abc&#39;&amp;&#34;。 &#34;&ABC放大器;&#34;或&#34; abc&#39;&amp;&#34;?而且对于&#34; ab _&#39;&#34;。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter

答案 1 :(得分:2)

因为你需要的替换可以是不同的(没有或空格),你不能使用固定的字符串(由于一次通过约束)。所以唯一的方法是使用动态替换。

直接方法:

让我们尝试找到要删除的字符,并在某些情况下保留其他字符:

var str = "abc's, test_s! & c++ c+ 'Dirty's'. and beautiful'...";

var re = /[^\w\s&.!'+-]+|\B'+|'+\B|(\+{2,})|\+|'*(_)'*/g; 

var result = str.replace(re, function (_, g1, g2) {
    if (g1) return g1;
    return (g2) ? ' ' : ''; });

console.log(result);

当找到下划线时,定义捕获组2(回调函数中为g2)并返回一个空格。

注意:在上面的例子中,术语“单词”采用正则表达式意义(字符类\w所以[a-zA-Z0-9_]除了下划线外),但是如果你想要更加严谨,例如,要排除数字附近的单引号,您需要稍微更改模式:

var re = /[^\w\s&.!'+-]+|(_)'*|([^a-z])'+|'+(?![a-z])|(\+{2,})|\+|^'+/gi;

var result = str.replace(re, function (_, g1, g2, g3) {
    if (g2) return g2;
    if (g3) return g3;
    return (g1) ? ' ' : ''; });

注意两种模式:

这两种模式包含6或7个子模式的交替,大多数时候可以匹配大约1或2个字符。请记住,要找到要删除的字符,这些模式必须测试6或7个替代项,然后才能为每个不能替换的字符失败。这是一个重要的成本,大部分时间都不需要替换角色。

有一种方法可以降低您可以在此处应用的费用:第一个字符歧视

我们的想法是尽可能避免测试每个子模式。这可以在这里完成,因为所有子模式都不以字母开头,因此如果您在开头添加前瞻,则可以快速跳过所有字母,而不必测试每个子模式。模式2的示例:

var re = /(?=[^a-z])(?:[^\w\s&.!'+-]+|(_)'*|([^a-z])'+|'+(?![a-z])|(\+{2,})|\+|^'+)/gi;

对于第一种模式,您可以跳过更多字符:

var re = /(?=[^a-z0-9\s&.!-])(?:[^\w\s&.!'+-]+|\B'+|'+\B|(\+{2,})|\+|'*(_)'*)/gi;

尽管有这些改进,但这两个模式需要很多步骤才能获得一个小字符串(~400)(但请考虑它是一个包含所有可能情况的示例字符串)

更间接的方法:

现在让我们尝试另一种方法,包括找到要替换的角色,但这次是在它之前的所有角色。

var re = /((?:[a-z]+(?:'[a-z]+)*|\+{2,}|[\s&.!-]+)*)(?:(_)|.)?/gi

var result = str.replace(re, function (_, g1, g2) {
    return g1 + ((g2) ? ' ' : '' );
});

(请注意,没有必要阻止灾难性的回溯,因为(?:a+|b+|c+)*后跟一个始终为真的子模式(?:d|e)?。旁边,整个模式永远不会失败,无论字符串或它的位置。)

要替换(允许的内容)的字符之前的所有字符都会被回调函数捕获并返回。

这种方式需要的工作量减少2倍以上才能完成同样的工作。

答案 2 :(得分:1)

您需要的是链接和交替运算符

function customReplace(str){
   return str.replace(/_/g, " ").replace(/^'|'$|[^a-zA-Z0-9 &-.!]|\+(?=[^+])/g,"");
}

正则表达式/^'|'$|[^a-zA-Z0-9 &-.!]|\+(?=[^+])/g结合了所有需要删除的内容。我们用空格替换所有_,我们最终返回。

\+(?=[^+])查找+后跟除+

之外的任何内容

此外,替换的顺序很重要。

答案 3 :(得分:1)

试试这个: by regex /(?!\b)'|'(?=\B)|^'|'$|[^\w\d\s&-.!]|\+(?=[^+])/gm

&#13;
&#13;
function sanitize(str) {
  var re = /(?!\b)'|'(?=\B)|^'|'$|[^\w\d\s&-.!]|\+(?=[^+])/gm;
  var subst = '';
  var tmp = str.replace(re, subst);  // remove all condition without (_) 
  var result = tmp.replace("_", " ");  // next replace (_) by ( ) space.
  return result;
}

document.querySelector('#sanitize').addEventListener('click', function() {

  document.querySelector('#output').innerHTML =
    sanitize(document.querySelector('#inputString').value);
});
&#13;
#inputString {
  width: 290px
}
#sanitize {
  background: #009afd;
  border: 1px solid #1777b7;
  border: none;
  color: #fff;
  cursor: pointer;
  height: 1.55em;
}
#output {
  background: #eee;
  margin-top: 5px;
  width: 295px;
}
&#13;
<input id="inputString" type="text" value="abc's test_s! & c++ c+ 'Dirty's'. and beau)'(tiful'..." />
<input id="sanitize" type="button" value="Sanitize it!" />
<div id="output"></div>
&#13;
&#13;
&#13;