2015-02-07 86 views
0

我想写一个正则表达式,使得接下来的事情就替换字符:取出并通过正则表达式

  1. _ - 用空格>替换
  2. + - >删除它,如果没有另一个+后(即c++ =>c++c+ - >c
  3. ' - >中删除它,如果它在该单词的开始或结束(即 Alin's - >Alin's'Alin's - >alin's
  4. &-.,! - 不要删除。
  5. 另一个特殊字符 - 删除

我想这样做,通过传递一个时间字符串

例如:

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/

我不喜欢我的代码,因为我敢肯定,它可能通过运行一次在字符串做。

任何帮助表示赞赏!

+1

什么是您给这个数据'“ABC的test_s输出C++ c +'肮脏的'。和美丽的'' – 2015-02-07 14:10:57

+0

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter – 2015-02-07 14:11:12

+0

@AhosanKarimAsik,输出是: “Abc's test s C++ c Dirty's 。和美丽的“ – 2015-02-15 16:01:44

回答

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=  
 
\t 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>

几点:

  • 一个通约束没有得到充分尊重,由于消毒与\ W拍摄的人物的义务。我没有找到任何其他方式。
  • 关于++规则:如果损害,+的任何序列都减1。
  • 只有在旁边有一个非字母数字字符的情况下,才会删除apostrophs。你应该怎么做,例如:“abc'&”。 “abc &”或“abc'&”?也适用于“ab_'s”。

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

你需要的是链接和交替操作

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

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

\+(?=[^+])查找+后跟任何东西,除了+

另外,的更换顺序很重要。

+0

这会删除'C++'中的第二个'+',这似乎并不是OP所需要的。您可能还需要包含预见以确保只删除独立'+' 秒。 – 2015-02-16 07:47:30

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倍的步骤来完成相同的工作。

1

试试这个:用正则表达式/(?!\b)'|'(?=\B)|^'|'$|[^\w\d\s&-.!]|\+(?=[^+])/gm

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); 
 
});
#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; 
 
}
<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>