regex 在正则表达式中使用sed,我如何在一行的末尾添加字符,从一开始就有一个可变长度的循环匹配

mccptt67  于 2023-08-08  发布在  其他
关注(0)|答案(3)|浏览(85)

我有一个Markdown文件,在一行的开头有一个或越来越多的“#”字符,它以降序标记标题,即一个散列是标题1,两个散列是标题2,等等。
我想将标题样式转换为在行的开始和结束处都使用'='字符的样式。
(This是跨多个文件的,因此我希望使用sed。)
范例:

# Heading 1

Some text

## Heading 2

Some more text

### Heading 3

And more

字符串
转换为:

= Heading 1 =

Some text

== Heading 2 ==

Some more text

=== Heading 3 ===

And more


我只想使用sed(不要评判我),我没有问题进行初始匹配。我的挑战是如何在匹配和替换'#'字符的行的末尾添加相同数量的'='字符?
脚注:我搜索了Stackoverflow和其他网站,没有发现任何内容涉及根据匹配中的字符数追加可变数量的字符。我还问了Chat-GPT,但正如我经常发现的那样,它只是以一个循环对话结束,在那里我重新处理了自己的问题并作为答案呈现。因此,我鼓起勇气在这里发帖,尽管我过去因为没有提出完美的问题而被殴打。请善良;)

ki0zmccv

ki0zmccv1#

使用GNU sed,您可以尝试:

sed -E 's/^#(.*)/=\1 =/;:a;s/^(=*)#(.*)/\1=\2=/;ta'

字符串
我们首先用=SOMETHING =s/^#(.*)/=\1 =/)替换任何#SOMETHING行。我们需要这种特殊处理,以便在尾随的=之前添加一个空格。接下来,我们添加一个循环标签(:a)。然后,我们用=...==SOMETHING=s/^(=*)#(.*)/\1=\2=/)替换=...=#SOMETHING,只要有#,我们就循环(ta)。
请注意,从技术上讲,如果你有一个#=的混合行,我们应该更具体一点,不要碰它们。范例:

sed -E '/^#+\s.*\S/{s/(#+)(.*\S)\s*/\1\2 /;:a;s/^(=*)#(.*)/\1=\2=/;ta}'

ffvjumwh

ffvjumwh2#

使用awk

awk '{
  where=match($0,"^#+"); 
  if (where) {
    out=""; 
    prefix="";
    for(i=1;i<=RLENGTH;i++){
      prefix=prefix"="
    }; 
    suffix=prefix; 
    for (i=2;i<=NF;i++){
      out=out$i
    }; 
    print prefix " " out " " suffix 
  } 
  else {print $0}}
'

字符串

uyto3xhc

uyto3xhc3#

使用awk,这将不那么复杂和《双城之战》,例如。使用GNU awk将第三个参数转换为match()

$ awk '
    match($0,/^(#+)(.*)/,a) {
        gsub(/#/,"=",a[1])
        $0 = a[1] a[2] " " a[1]
    }
    { print }
' file
= Heading 1 =

Some text

== Heading 2 ==

Some more text

=== Heading 3 ===

And more

字符串
或者在每个Unix机器上的任何shell中可移植地使用任何awk:

awk '
    match($0,/^#+/) {
        hd = substr($0,1,RLENGTH)
        tl = substr($0,RSTART+RLENGTH)
        gsub(/#/,"=",hd)
        $0 = hd tl " " hd
    }
    { print }
' file

相关问题