在这种情况下,有三种方法:
使用正则表达式查找您想要保留的所有内容,然后将所有这些部分粘贴在一起。
-
使用正则表达式查找您不想保留的东西,然后通过替换它们将它们扔掉(这是其他一些答案所做的)。
按照一个答案的建议,自己解析字符串。
我们将考虑正则表达式解决方案。编写正则表达式的关键是写下你想要它做什么的叙述性描述。然后将其转换为实际的正则表达式语法。否则,当你随意尝试一件事或另一件事时,你的眼睛会开始流血。
要找到你想保留的东西,叙述性描述是:
任何带括号的字符串(包括前面的空格)或空格(或字符串开头)后跟单个字母、或标点符号。
把它变成一个正则表达式:
including preceding spaces: \s*
any parenthesized string: \(.*?\)
or: |
space or beginning of string: (^|\s+)
any letter: \w
punctuation: [.]
所以相关的正则表达式是/\s*\(.*?\)|(^|\s+)\w|[.]/。
>> parts = str.match(/\s*\(.*?\)|(^|\s+)\w/g);
<< ["T", " t", " t", " (test)", ".", " T", " (test test)", " t", " t", "."]
>> parts.join('')
<< "T t t (test). T (test test) t t."
如果你想采用相反的方法,即找到你不想保留的部分,用空字符串替换,那么叙述是
任何前面有另一个字母的字母,除非更早有一个左括号,中间没有右括号。
这里的问题是 unless come early 部分,在正则表达式中,这就是所谓的否定后视;正则表达式的 JS 风格不支持。
这就是为什么其他一些答案使用正则表达式的技术,即“(1)第一个字母或括号表达式的整个序列,(2)后跟更多字母”,并捕获(1)部分。然后用 (1) 替换整个字符串,使用 $1 反向引用,它具有删除 (2) 的效果。这也很好用。
换句话说,要丢弃A(如果前面有B),它们会匹配(B)A,然后将整个匹配替换为B。
使用split
为了完整起见,您还可以考虑使用空格、标点符号和括号括起来的表达式:
str = "Test (test). test";
>> pieces = str.split(/(\(.*?\)|\s+|[.])/);
<< ["Test", " ", "", "(test)", "", ".", "", " ", "test"]
// Remove empty strings
>> pieces = pieces . filter(Boolean)
<< ["Test", " ", "(test)", ".", " ", "test"]
// Take first letter if not parenthesized
>> pieces = pieces . map(function(piece) {
return piece[0] === '(' ? piece : piece[0];
});
<< ["T", " ", "(test)", ".", " ", "t"]
// Join them back together
>> pieces . join('')
<< "T (test). t"
整个解决方案就变成了
function abbreviate_words_outside_parentheses(str) {
return str .
split(/(\(.*?\)|\s+|[.])/) .
filter(Boolean) .
map(function(piece) { return piece[0] === '(' ? piece : piece[0]; }) .
join('')
;
}
如果您认为将来可能希望进行其他类型的转换,这种程序方法可能更可取,这可能很难使用正则表达式处理。