在多行字符串中,如何匹配每行以竖线字符开头的新行序列
Within a multiline string how does one match sequences of new lines where each line starts with the pipe character
嘿,我有一个类似这样的字符串:
字符串:
foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
我需要一个匹配第一个“|”开始的所有内容的正则表达式在一行开始到不以“|”开头的第一行(作为一场比赛)。
所以所示示例中的匹配将是这样的:
正确匹配:
[
|foo | bar
|foo bar
|bar foo foo
,
|bar foo
|foo bar
]
我想出了这个 /\|([\s\S]+)(\n\|)/g
但它与以下内容匹配,但不正确:
不正确的匹配:
[
| bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|
]
希望您能理解我的需要,感谢您的宝贵时间!
回答
按照你的问题,从第一个“|”开始匹配所有内容在第一行不以“|”开头的行开头,您可以使用此正则表达式:
/^\|([\s\S]*?)(?:(?!^[^\|])[\s\S])*/gm
需要注意 m
标志(多行)才能匹配多行字符串。
给你的示例字符串
foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
这将匹配
|foo | bar
|foo bar
|bar foo foo
和
|bar foo
|foo bar
工作原理:
^\|
匹配任何以“|”开头的行特点。然后,([\s\S]*?)
匹配 0 个或多个任何字符,包括新行“Lazily”(意味着只捕获最小值)。最后 (?:(?!^[^\|])[\s\S])*
匹配到不以“|”开头的新行 (^
) ([^\|]
).
这里有一个 link 到 Regexr,详细说明了它的工作原理和实际应用示例。
const str =
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`
console.log(str.match(/^\|([\s\S]*?)(?:(?!^[^\|])[\s\S])*/gm))
一种方法仅基于 match
might not in any case work for the OP's requirement(s). But a working solution definitely can be achieved with both a regex based split
and a sanitizing filter
...类似于 ...
`multilines`.split(/(?:^[^|].*\n)+/gm).filter(str => str !== '' && str !== '\n');
这是为什么?
由于 OP 希望保留任何以连续换行为特征的子字符串,每行都以 |
开头,因此 OP 只需要在每个不以 [=18= 开头的新行处拆分多行字符串].
因此第一个有效的正则表达式可能是 /^[^|].*\n/gm
。读起来是这样的...
/ ... /m
在 m
多行模式下运行,从而使 ^
能够匹配字符串中的每个新行。
^[^|]
在每个新行的开头匹配一个不是竖线的字符/|
... 然后 ...
.*\n
匹配任何其他内容,包括最后一个换行符
此匹配项将用于 split
操作,从而将 OP 正在查找的行与应该从 OP 所需结果中排除的行分开。
由于正则表达式还不是很理想,并且由于 split
的性质,结果具有一些伪像 ...
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`.split(/^[^|].*\n/gm)
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
foo | bar
bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
`.split(/^[^|].*\n/gm)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
...我们在下一次代码迭代中将其删除。
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`.split(/(?:^[^|].*\n)+/gm)
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
foo | bar
bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
`.split(/(?:^[^|].*\n)+/gm)
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`.split(/(?:^[^|].*\n)+/gm).filter(str => str !== '' && str !== '\n')
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
foo | bar
bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
`.split(/(?:^[^|].*\n)+/gm).filter(str => str !== '' && str !== '\n')
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
第一个正则表达式 ... /^[^|].*\n/gm
... 已改进为 /(?:^[^|].*\n)+/gm
。因此,第二个版本现在匹配不需要的换行符序列(不捕获它们......(?: ...)
)。
结果几乎涵盖了OP的要求。但是对于边缘情况,人们仍然会在结果数组中遇到伪影。因此,为了始终处于保存状态,需要通过 filter
条件对后者进行消毒。
嘿,我有一个类似这样的字符串:
字符串:
foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
我需要一个匹配第一个“|”开始的所有内容的正则表达式在一行开始到不以“|”开头的第一行(作为一场比赛)。 所以所示示例中的匹配将是这样的:
正确匹配:
[
|foo | bar
|foo bar
|bar foo foo
,
|bar foo
|foo bar
]
我想出了这个 /\|([\s\S]+)(\n\|)/g
但它与以下内容匹配,但不正确:
不正确的匹配:
[
| bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|
]
希望您能理解我的需要,感谢您的宝贵时间!
回答
按照你的问题,从第一个“|”开始匹配所有内容在第一行不以“|”开头的行开头,您可以使用此正则表达式:
/^\|([\s\S]*?)(?:(?!^[^\|])[\s\S])*/gm
需要注意 m
标志(多行)才能匹配多行字符串。
给你的示例字符串
foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
这将匹配
|foo | bar
|foo bar
|bar foo foo
和
|bar foo
|foo bar
工作原理:
^\|
匹配任何以“|”开头的行特点。然后,([\s\S]*?)
匹配 0 个或多个任何字符,包括新行“Lazily”(意味着只捕获最小值)。最后 (?:(?!^[^\|])[\s\S])*
匹配到不以“|”开头的新行 (^
) ([^\|]
).
这里有一个 link 到 Regexr,详细说明了它的工作原理和实际应用示例。
const str =
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`
console.log(str.match(/^\|([\s\S]*?)(?:(?!^[^\|])[\s\S])*/gm))
一种方法仅基于 match
might not in any case work for the OP's requirement(s). But a working solution definitely can be achieved with both a regex based split
and a sanitizing filter
...类似于 ...
`multilines`.split(/(?:^[^|].*\n)+/gm).filter(str => str !== '' && str !== '\n');
这是为什么?
由于 OP 希望保留任何以连续换行为特征的子字符串,每行都以 |
开头,因此 OP 只需要在每个不以 [=18= 开头的新行处拆分多行字符串].
因此第一个有效的正则表达式可能是 /^[^|].*\n/gm
。读起来是这样的...
/ ... /m
在m
多行模式下运行,从而使^
能够匹配字符串中的每个新行。^[^|]
在每个新行的开头匹配一个不是竖线的字符/|
... 然后 ....*\n
匹配任何其他内容,包括最后一个换行符
此匹配项将用于 split
操作,从而将 OP 正在查找的行与应该从 OP 所需结果中排除的行分开。
由于正则表达式还不是很理想,并且由于 split
的性质,结果具有一些伪像 ...
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`.split(/^[^|].*\n/gm)
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
foo | bar
bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
`.split(/^[^|].*\n/gm)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
...我们在下一次代码迭代中将其删除。
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`.split(/(?:^[^|].*\n)+/gm)
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
foo | bar
bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
`.split(/(?:^[^|].*\n)+/gm)
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar`.split(/(?:^[^|].*\n)+/gm).filter(str => str !== '' && str !== '\n')
);
console.log(
`foo | bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
foo | bar
bar
|foo | bar
|foo bar
|bar foo foo
foo bar
|bar foo
|foo bar
bar
`.split(/(?:^[^|].*\n)+/gm).filter(str => str !== '' && str !== '\n')
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
第一个正则表达式 ... /^[^|].*\n/gm
... 已改进为 /(?:^[^|].*\n)+/gm
。因此,第二个版本现在匹配不需要的换行符序列(不捕获它们......(?: ...)
)。
结果几乎涵盖了OP的要求。但是对于边缘情况,人们仍然会在结果数组中遇到伪影。因此,为了始终处于保存状态,需要通过 filter
条件对后者进行消毒。