正则表达式-用相同数量的另一个字符替换一个字符的序列

发布于 2024-12-03 13:24:49 字数 479 浏览 0 评论 0原文

假设我有一个像这样的字符串:

=====

我想用这个替换它:

-----

我只想在它包含超过一定数量的该字符时替换它(我们会说> 3)。

所以,这些应该是替换:

=== -> ===
==== -> ----
===== -> -----

应用程序是我想用 2 级标记替换 markdown 中的所有 1 级标题标记,而不更改嵌入的代码块。

我知道我可以这样做:

/=/-/g,但这会匹配任何带有等号的内容(if (x == y)),这是不可取的。

或者这样:

/===+/----/g,但这并没有考虑到原始匹配字符串的长度。

这可能吗?

Let's say I have a string like this:

=====

and I want to replace it with this:

-----

I only want to replace it if it has more than a certain number of that character (we'll say > 3).

So, these should be the replacements:

=== -> ===
==== -> ----
===== -> -----

The application is I want to replace all level 1 heading marks in markdown with a level 2 mark, without changing embedded code blocks.

I know I can do this:

/=/-/g, but this matches anything with an equals sign (if (x == y)), which is undesirable.

or this:

/===+/----/g, but this doesn't account for the length of the original matched string.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

奈何桥上唱咆哮 2024-12-10 13:24:49

使用 Perl 是可能的:

my $string = "===== Hello World ====";
$string =~ s/(====+)/"-" x length($1)/eg;
# $string contains ----- Hello World ----

标志 /e 使 Perl 在 s/// 的第二部分执行表达式。
你可以用 oneliner 试试这个:

perl -e '$ARGV[0] =~ s/(====+)/"-" x length($1)/eg; print $ARGV[0]' "===== Hello World ===="

It's possible with Perl:

my $string = "===== Hello World ====";
$string =~ s/(====+)/"-" x length($1)/eg;
# $string contains ----- Hello World ----

Flag /e makes Perl execute expression in second part of s///.
You may try this with oneliner:

perl -e '$ARGV[0] =~ s/(====+)/"-" x length($1)/eg; print $ARGV[0]' "===== Hello World ===="
落日海湾 2024-12-10 13:24:49

取决于您使用的语言。基本上,在某些语言中,您可以将代码放在正则表达式的右侧,允许您执行以下操作:(这是在 perl 中):

s/(=+)/(length($1) > 3 ? "-" : "=") x length($1)/e

'e' 标志告诉 perl 执行正则表达式右侧的代码表达式而不是仅仅将其解析为字符串。

Depending what language you're using. Basically, in some languages, you can put code in the right side of the regexp, allowing you to do something like this: (this is in perl):

s/(=+)/(length($1) > 3 ? "-" : "=") x length($1)/e

The 'e' flag tells perl to execute the code in the right side of the expression instead of just parsing it as a string.

雄赳赳气昂昂 2024-12-10 13:24:49

我也在寻找类似这样的纯正则表达式解决方案。我在SO上没有找到,所以我解决了。

简短版本:这里是正则表达式:

((?<==== )=)|(=(?====))|((?<===)=(?==))|((?<==)=(?===))

这是我如何到达那里,使用R:

str <- " = == === ==== ===== ====== ======="

gsub("=(?====)",      "-", str, perl = TRUE) # (1) Pos. lookahead
gsub("(?<====)=",     "-", str, perl = TRUE) # (2) Pos. look-behing
gsub("(?<===)=(?==)", "-", str, perl = TRUE) # (3) Middle part for cases of 4 or 5 ='s (1/2)
gsub("(?<==)=(?===)", "-", str, perl = TRUE) # (4) Middle part for cases of 4 or 5 ='s (2/2)

# Combining all, we have:
gsub("((?<====)=)|(=(?====))|((?<===)=(?==))|((?<==)=(?===))", "-", str, perl = TRUE) # (5)

(1) = == === -=== --=== ---=== ----===
(2) = == === ===- ===-- ===--- ===----
(3) = == === ==-= ==--= ==---= ==----=
(4) = == === =-== =--== =---== =----==
(5) = == === ---- ----- ------ -------

更简单的正则表达式的替代方法(但需要 3 个步骤)

# First, deal with 4 & 5 equal signs with negative look-behind and lookahead
str <- gsub("(?<!=)={4}(?!=)", "----",     str, perl = TRUE) # (2.1)
str <- gsub("(?<!=)={5}(?!=)", "-----",    str, perl = TRUE) # (2.2)

# Then use regex (3) from above for 6+ equal signs
str <- gsub("((?<====)=)|(=(?====))", "-", str, perl = TRUE) # (2.3)

(2.1) = == === ---- ===== ====== =======
(2.2) = == === ---- ----- ====== =======
(2.3) = == === ---- ----- ------ -------

I was also looking for a pure regex solution for something like this. I didn't find one on SO, so I worked it out.

Short version: here is the regex:

((?<====)=)|(=(?====))|((?<===)=(?==))|((?<==)=(?===))

Here is how I got there, using R:

str <- " = == === ==== ===== ====== ======="

gsub("=(?====)",      "-", str, perl = TRUE) # (1) Pos. lookahead
gsub("(?<====)=",     "-", str, perl = TRUE) # (2) Pos. look-behing
gsub("(?<===)=(?==)", "-", str, perl = TRUE) # (3) Middle part for cases of 4 or 5 ='s (1/2)
gsub("(?<==)=(?===)", "-", str, perl = TRUE) # (4) Middle part for cases of 4 or 5 ='s (2/2)

# Combining all, we have:
gsub("((?<====)=)|(=(?====))|((?<===)=(?==))|((?<==)=(?===))", "-", str, perl = TRUE) # (5)

(1) = == === -=== --=== ---=== ----===
(2) = == === ===- ===-- ===--- ===----
(3) = == === ==-= ==--= ==---= ==----=
(4) = == === =-== =--== =---== =----==
(5) = == === ---- ----- ------ -------

Alternative method for a less convoluted regex (but requires 3 steps)

# First, deal with 4 & 5 equal signs with negative look-behind and lookahead
str <- gsub("(?<!=)={4}(?!=)", "----",     str, perl = TRUE) # (2.1)
str <- gsub("(?<!=)={5}(?!=)", "-----",    str, perl = TRUE) # (2.2)

# Then use regex (3) from above for 6+ equal signs
str <- gsub("((?<====)=)|(=(?====))", "-", str, perl = TRUE) # (2.3)

(2.1) = == === ---- ===== ====== =======
(2.2) = == === ---- ----- ====== =======
(2.3) = == === ---- ----- ------ -------
温柔戏命师 2024-12-10 13:24:49

特别是对于此 Markdown 标题用例,您可以利用这些始终位于行开头的事实:

/(^=|(?<==)=)/-/

将替换位于行开头或前面有 '=' 的所有 '=' 字符。

不过,它会在文本中删除双“==”...也许有人可以对此进行改进?

Specifically for this Markdown headings use case, you can use the fact that these always come at the start of a line:

/(^=|(?<==)=)/-/

will replace all the '=' characters that are either at the start of a line, or have a '=' before them.

It'll zap double '==' in the text though... perhaps someone can improve on that?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文