JavaScript Regex 将单词替换为其第一个字母,除非在括号内
JavaScript Regex replace words with their first letter except when within parentheses
我正在寻找JavaScript正则表达式,它将仅用每个单词的第一个字母替换文本块中的单词,但如果括号内有单词,请用括号保持完整。目的是创建一个助记符设备,用于记住剧本或戏剧剧本中的台词。我希望实际的行减少到第一个字母,但舞台方向(在括号中(保持不变。
例如:
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.
我对正则表达式的理解很差。我已经研究了几天,尝试了很多东西,但似乎无法理解解决方案。
您可以通过对正则表达式进行小幅调整来实现此目的:
/('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"
为了保持正则表达式的简单性,您可以使用回调机制来跟踪左括号和右括号:
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);
在这种情况下,有三种方法:
-
使用正则表达式查找要保留的所有内容,然后将所有这些部分粘贴在一起。
-
使用正则表达式找到你不想保留的东西,然后通过替换它们来扔掉它们(这是其他一些答案所做的(。
-
自己解析字符串,正如一个答案所暗示的那样。
我们将考虑正则表达式解决方案。编写正则表达式的关键是写下你想要它做什么的叙述性描述。然后将其转换为实际的正则表达式语法。否则,当您随机尝试一件事或另一件事时,您的眼睛会开始流血。
要找到您要保留的内容,叙述性描述是:
任何带括号的字符串(包括前面的空格(或空格(或字符串的开头(,后跟单个字母或标点符号。
要将其转换为正则表达式:
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."
如果你想采取相反的方法,即找到你不想保留的片段,用空字符串代替,那么叙事是
任何在另一个字母之前有另一个字母的字母,除非更早出现,否则有一个左括号,中间没有右括号。
这里的问题是除非提前到来,用正则表达式术语来说,这就是所谓的负向后看;正则表达式的JS风格不支持这一点。
这就是为什么其他一些答案使用正则表达式的技术,它说"(1(第一个字母或整个括号表达式序列,(2(后跟更多字母",并捕获(1(部分。然后使用$1
反向引用将整个字符串替换为 (1(,这具有删除 (2( 的效果。这也很好用。
换句话说,如果前面有一个B
,则扔掉一个A
,它们在(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('')
;
}
如果您认为将来可能想要执行其他类型的转换,则此过程方法可能更可取,这可能很难使用正则表达式进行处理。
您需要使用捕获组和前瞻断言来实现预期的结果。
> "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|$)
正面展望断言匹配后必须跟一个空格或行锚点的末尾,这反过来意味着我们匹配一个完整的单词。
- JavaScript Regex 将单词替换为其第一个字母,除非在括号内
- Regex或javascript每X个连续单词中有一个单词
- Regex模式,用于检查字符串中每个单词的第一个字母(如果是Javascript中的大写字母)
- regex如何删除特定单词后的逗号
- RegEx:在单词边界添加加号
- Regex目标特定单词基于两个起始行条件
- Regex:匹配以“AM”结尾的单词(不区分大小写比较)
- Regex以匹配url中的单个单词
- Regex赢得'不要像预期的那样匹配单词
- Regex:使用javascript测试最后一个单词后的url中是否存在最后一个斜杠
- regex,用于修改单词末尾特定大小写的字符
- Javascript RegEx在字符后匹配单词
- 获取所有4个字母的单词Regex
- Regex获取每个单词的中间部分javascript
- Regex单词边界(退格)测试用例
- regex过滤单词长度最小的句子
- 使用js-Regex的字符串的第N个单词
- Regex,替换所有以@开头的单词
- Regex以匹配整数或单词“”;“其他”;,不区分大小写
- Regex根据单词匹配URL