我正在寻找JavaScript Regex,它将替换文本块中的单词,只有每个单词的第一个字母但是如果括号内有单词,则用括号保留它们。 目的是创建一个助记符设备,用于记住剧本或戏剧剧本中的行。我希望实际的行减少到第一个字母,但阶段方向(在括号中)不变。
例如:
Test test test (test). Test (test test) test test.
会产生结果:
T t t (test). T (test test) t t.
使用:
.replace(/(\w)\w*/g,'$1')
收益率:
T t t (t). T (t t) t t.
我对正则表达式的理解很差。我已经研究了好几天了,尝试了很多东西,但似乎无法解决问题。
答案 0 :(得分:2)
你可以通过对你的正则表达式进行一些小调整来完成这个:
/(\w|\([^)]+\))\w*/
添加的部分\([^)]+\)
匹配两对括号内的所有内容。
"Test test test (test). Test (test test) test test.".replace(/(\w|\([^)]+\))\w*/g,'$1')
>"T t t (test). T (test test) t t."
编辑:解决评论中提出的问题
"Test test test (test). Test (test. test.) test test. test(test) (test)test".replace(/(\w|\([^)]+)\w*/g,'$1')
>"T t t (test). T (test. test.) t t. t(test) (test)t"
答案 1 :(得分:1)
在这种情况下,有三种方法:
使用正则表达式查找要保留的所有内容,然后将所有这些内容粘贴在一起。
使用正则表达式查找不想要保留的内容,然后通过替换它们来抛弃它们(这是其他一些答案所做的)。
正如一个答案所暗示的那样,自己解析字符串。
我们将考虑regexp解决方案。编写正则表达式的关键是写下你想要它做什么的叙述性描述。然后将其转换为实际的regexp语法。否则,当你随机尝试一件或另一件事时,你的眼睛会开始出血。
为了找到你想要保留的内容,叙述性描述是:
任何带括号的字符串(包括前面的空格)或空格(或字符串的开头)后跟一个字母或标点符号。
将其转换为正则表达式:
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."
如果你想采用相反的方法,即找到不想要保留的部分,用空字符串替换,那么叙述就是
任何前面带有另一个字母的字母,除非早先,否则会有一个开头括号,没有插入右括号。
这里的问题是,除非早先发布部分,在正则表达式中,这就是所谓的负面观察; regexp的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('')
;
}
如果您认为将来可能希望进行其他类型的转换,这种程序方法可能更好,这可能很难使用正则表达式来处理。
答案 2 :(得分:1)
为了保持正则表达式的简单,您可以使用回调机制来跟踪开括号和右括号:
var t = 'Test test test (test). Test (test test) test test.';
// keep track of open state and last index
var s = {
open: false,
index: 0
};
var res = t.replace(/\w+/g, function($0, index) {
// update state
for (var i = s.index; i < index; ++i) {
if (t[i]=='(' || t[i] == ')') {
s.open = !s.open; // assume balanced parentheses
}
}
s.index = index;
// return first letter if outside of parentheses
return s.open ? $0 : $0[0];
});
console.log(res);
&#13;
答案 3 :(得分:0)
您需要使用捕获组和先行断言才能达到预期的结果。
> "Test test test (test). Test (test test) test test".replace(/(^[^\s(]|\s[^\s(])[^()\s]*(?=\s|$)/g, "$1")
'T t t (test). T (test test) t t'
(^[^\s(]|\s[^\s(])
捕获每个单词的第一个字母,该单词不得为空格或(
。
[^()\s]*
匹配任何字符,但不匹配(
或)
或空格。
(?=\s|$)
正向前瞻断言,匹配必须后跟行锚的空格或末尾,这反过来意味着我们匹配完整的单词。