在特定单词后打破字符串并将其保留在新行(正则表达式)

Bra*_*roy 8 html javascript regex string jquery

假设我有一个文本字段,用户可以在其中提交代码片段.我想检测字符串中何时出现特定单词,然后对该单词后面的单词/字符执行某些操作.

假设我们有一个字符串,在单词睡衣之后我想在没有缩进的新行上启动其余代码.(非常类似于代码美化器的工作方式.)输出将在内部呈现pre,因此我不需要任何<br>标记或其他HTML标记.

虽然有一些捕获量.

  1. 一个单词(睡衣)之后的所有内容都必须在与之前一行相同的"级别"(同样数量的制表符缩进)的新行上开始.
  2. 逗号应始终以新行开头,并使用制表符反向缩进
  3. 当有另一个字符时,让我们说一个感叹号!,下面的代码必须从一个新的行开始,并以制表符作为缩进.

例:

输入:

Bananas! Apples and pears walk down pyjamas the street! and they say pyjamas hi to eachother, pyjamas But then! some one else comes pyjamas along pyjamas Who is he?, pyjamas I don't know who! he is pyjamas whatever,,
Run Code Online (Sandbox Code Playgroud)

输出:

Bananas!
    Apples and pears walk down pyjamas
    the street!
        and they say pyjamas
        hi to eachother
    , pyjamas
    But then!
        some one else comes pyjamas
        along pyjamas
        Who is he?
    , pyjamas
    I don't know who!
        he is pyjamas
        whatever
    ,
,
Run Code Online (Sandbox Code Playgroud)

我正在使用jQuery,所以如果你愿意,你可以使用它.

这是上面代码的小提琴,所以你可以测试它.到目前为止,我的结果并不是很好.(在textarea中键入内容,输出将会改变.)由于我目前对正则表达式几乎不了解,我需要一些帮助.

到目前为止我所拥有的:

var a = $("textarea").val(),
    b = a.split('!').join("!\n  "),
    c = b.split('pyjamas').join("pyjamas \n");

$("textarea").keyup(function() {
    $("#output>pre").html(c);
});
Run Code Online (Sandbox Code Playgroud)

Mar*_*der 13

这是一个简单的方法,不需要递归函数,甚至可以在没有正则表达式的情况下完成(但我发现这里很方便).

function indent(str)
{
    var tabs = function(n) { return new Array(n+1).join('\t'); }

    var tokens = str.match(/!|,|pyjamas|(?:(?!pyjamas)[^!,])+/g);
    var depth = 0;
    var result = '';
    for (var i = 0; i < tokens.length; ++i)
    {
        var token = tokens[i];
        switch(token)
        {
        case '!':
            ++depth;
            result += token + '\n' + tabs(depth);
            break;
        case ',':
            --depth;
            result += '\n' + tabs(depth) + token;
            break;
        case 'pyjamas':
            result += token + '\n' + tabs(depth);
            break;
        default:
            result += token;
            break;
        }
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

首先,我们定义一个返回一串n选项卡的函数(为方便起见).

然后我们将流程分为两个步骤.首先,我们tokenise字符串-这就是我们将其分成!,,,pyjamas和别的.(最后有一个关于正则表达式的解释,但你也可以通过其他方式进行标记化.)然后,我们只需逐个移动标记,保持当前的缩进级别depth.

  • 如果是!我们增加深度,则打印!换行符和制表符.
  • 如果它是,我们减少深度,打印换行符,选项卡然后再打印,.
  • 如果是pyjamas,我们只需打印它和换行符以及标签.
  • 如果是其他任何东西,我们只需打印该令牌.

而已.您可能要增加一些理智检查深度不变成负(即你有更多的,!) -目前,将简单的没有任何标签可以呈现,但你需要编写额外!之后得到深度回升到1.这很容易处理,但我不知道你的假设或要求是什么.

换行后它也不会占用额外的空格(参见最后的编辑).

工作演示.

现在为正则表达式:

/
  !               # Match a literal !
|                 # OR
  ,               # Match a literal ,
|                 # OR
  pyjamas         # Match pyjamas
|                 # OR
  (?:             # open a non-capturing group
    (?!pyjamas)   # make sure that the next character is not the 'p' of 'pyjamas'
    [^!,]         # match a non-!, non-, character
  )+              # end of group, repeat once or more (as often as possible)
/g
Run Code Online (Sandbox Code Playgroud)

g找到所有比赛(而不是仅仅是第一个).ECMAScript 6将带有一个y修饰符,这将使标记化更容易 - 但令人讨厌的是,这个y修饰符是ECMAScript自己的发明,而提供此功能的其他任何风格都使用\G模式中的锚点.

如果你不熟悉正则表达式中的一些更高级的概念,我建议你参考这个很棒的教程:

编辑:

这是一个更新版本,修复了我提到的关于换行后空格的上述警告.在处理结束时,我们只需删除标签后的所有空格:

result = result.replace(/^(\t*)[ ]+/gm, '$1');
Run Code Online (Sandbox Code Playgroud)

正则表达式匹配行的开头,然后捕获零个或多个选项卡,然后捕获尽可能多的空格.空间周围的方括号不是必需的,但提高了可读性.修饰符g再次找到所有这样的匹配并在一行的开头m进行^匹配(而不是仅仅是字符串的开头).在替换字符串$1中指的是我们在括号中捕获的内容 - 即所有这些选项卡.所以回写标签但吞下空格.

工作演示.