JavaScript正则表达式用第一个字母替换单词,但在括号内除外

时间:2015-04-06 00:10:52

标签: javascript regex replace parentheses

我正在寻找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.

我对正则表达式的理解很差。我已经研究了好几天了,尝试了很多东西,但似乎无法解决问题。

4 个答案:

答案 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)

在这种情况下,有三种方法:

  1. 使用正则表达式查找要保留的所有内容,然后将所有这些内容粘贴在一起。

  2. 使用正则表达式查找想要保留的内容,然后通过替换它们来抛弃它们(这是其他一些答案所做的)。

  3. 正如一个答案所暗示的那样,自己解析字符串。

  4. 我们将考虑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)

为了保持正则表达式的简单,您可以使用回调机制来跟踪开括号和右括号:

&#13;
&#13;
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;
&#13;
&#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'

DEMO

  • (^[^\s(]|\s[^\s(])捕获每个单词的第一个字母,该单词不得为空格或(

  • [^()\s]*匹配任何字符,但不匹配()或空格。

  • (?=\s|$)正向前瞻断言,匹配必须后跟行锚的空格或末尾,这反过来意味着我们匹配完整的单词。