JavaScript 正则表达式用第一个字母替换单词,除非在括号内
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,'')
产量:
T t t (t). T (t t) t t.
我对正则表达式的理解很差。我已经研究它好几天了,尝试了很多东西,但似乎无法解决问题。
您需要使用捕获组和先行断言才能获得预期的结果。
> "Test test test (test). Test (test test) test test".replace(/(^[^\s(]|\s[^\s(])[^()\s]*(?=\s|$)/g, "")
'T t t (test). T (test test) t t'
(^[^\s(]|\s[^\s(])
捕获每个单词的第一个字母,不能是 space 或 (
.
[^()\s]*
匹配任何字符,但不匹配 (
或 )
或 space.
(?=\s|$)
正向前瞻断言匹配后必须跟一个 space 或行尾锚点,这反过来意味着我们匹配一个完整的单词。
您可以通过对正则表达式进行一些小的调整来完成此操作:
/(\w|\([^)]+\))\w*/
添加的部分\([^)]+\)
匹配两对括号内的所有内容。
"Test test test (test). Test (test test) test test.".replace(/(\w|\([^)]+\))\w*/g,'')
>"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,'')
>"T t t (test). T (test. test.) t t. t(test) (test)t"
遇到这种情况,有以下三种处理方法:
使用正则表达式查找您想要保留的所有内容,然后将所有这些片段粘贴在一起。
使用正则表达式查找您不想保留的东西,然后通过替换它们将它们扔掉(这是其他一些答案所具有的完成)。
如一个答案所示,您自己解析字符串。
我们将考虑正则表达式解决方案。编写正则表达式的关键是写下你想要它做什么的叙述性描述。然后将其转换为实际的正则表达式语法。否则,当您随机尝试某件事时,您的眼睛会开始流血。
要找到你想保留的,叙述描述为:
Any parenthesized string (including preceding spaces) or space (or beginning of string) followed by a single letter, or punctuation.
要将其转换为正则表达式:
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."
如果你想采用相反的方法,即找到你不想保留的部分,用空字符串替换,那么叙述是
Any letter which is preceded by another letter, unless coming earlier there is an opening parentheses with no intervening closing parenthesis.
这里的问题是 unless coming earlier 部分,在正则表达式中这就是所谓的负向后视;正则表达式的 JS 风格不支持。
这就是为什么其他一些答案使用正则表达式技术的原因,即“(1) 第一个字母或括号表达式的整个序列,(2) 后跟更多字母”,并捕获 (1) 部分。然后使用 </code> 反向引用将整个字符串替换为 (1),这具有删除 (2) 的效果。这也很好。</p>
<p>换句话说,如果前面有 <code>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('')
;
}
如果您认为您将来可能想要进行其他类型的转换,那么使用正则表达式可能难以处理,这种过程方法可能更可取。
为了保持正则表达式简单,您可以使用回调机制来跟踪左括号和右括号:
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([=10=], 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 ? [=10=] : [=10=][0];
});
console.log(res);
我正在寻找 JavaScript 正则表达式,它将文本块中的单词仅替换为每个单词的第一个字母,但是如果括号内有单词,请将它们保留在括号中。 目的是创建一个助记设备,用于记住剧本或戏剧剧本中的台词。我希望将实际台词缩减为首字母,但舞台方向(括号内)保持不变。
例如:
Test test test (test). Test (test test) test test.
将产生结果:
T t t (test). T (test test) t t.
使用:
.replace(/(\w)\w*/g,'')
产量:
T t t (t). T (t t) t t.
我对正则表达式的理解很差。我已经研究它好几天了,尝试了很多东西,但似乎无法解决问题。
您需要使用捕获组和先行断言才能获得预期的结果。
> "Test test test (test). Test (test test) test test".replace(/(^[^\s(]|\s[^\s(])[^()\s]*(?=\s|$)/g, "")
'T t t (test). T (test test) t t'
(^[^\s(]|\s[^\s(])
捕获每个单词的第一个字母,不能是 space 或(
.[^()\s]*
匹配任何字符,但不匹配(
或)
或 space.(?=\s|$)
正向前瞻断言匹配后必须跟一个 space 或行尾锚点,这反过来意味着我们匹配一个完整的单词。
您可以通过对正则表达式进行一些小的调整来完成此操作:
/(\w|\([^)]+\))\w*/
添加的部分\([^)]+\)
匹配两对括号内的所有内容。
"Test test test (test). Test (test test) test test.".replace(/(\w|\([^)]+\))\w*/g,'')
>"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,'')
>"T t t (test). T (test. test.) t t. t(test) (test)t"
遇到这种情况,有以下三种处理方法:
使用正则表达式查找您想要保留的所有内容,然后将所有这些片段粘贴在一起。
使用正则表达式查找您不想保留的东西,然后通过替换它们将它们扔掉(这是其他一些答案所具有的完成)。
如一个答案所示,您自己解析字符串。
我们将考虑正则表达式解决方案。编写正则表达式的关键是写下你想要它做什么的叙述性描述。然后将其转换为实际的正则表达式语法。否则,当您随机尝试某件事时,您的眼睛会开始流血。
要找到你想保留的,叙述描述为:
Any parenthesized string (including preceding spaces) or space (or beginning of string) followed by a single letter, or punctuation.
要将其转换为正则表达式:
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."
如果你想采用相反的方法,即找到你不想保留的部分,用空字符串替换,那么叙述是
Any letter which is preceded by another letter, unless coming earlier there is an opening parentheses with no intervening closing parenthesis.
这里的问题是 unless coming earlier 部分,在正则表达式中这就是所谓的负向后视;正则表达式的 JS 风格不支持。
这就是为什么其他一些答案使用正则表达式技术的原因,即“(1) 第一个字母或括号表达式的整个序列,(2) 后跟更多字母”,并捕获 (1) 部分。然后使用 </code> 反向引用将整个字符串替换为 (1),这具有删除 (2) 的效果。这也很好。</p>
<p>换句话说,如果前面有 <code>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('')
;
}
如果您认为您将来可能想要进行其他类型的转换,那么使用正则表达式可能难以处理,这种过程方法可能更可取。
为了保持正则表达式简单,您可以使用回调机制来跟踪左括号和右括号:
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([=10=], 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 ? [=10=] : [=10=][0];
});
console.log(res);