使用sed将多行文本中的一个匹配模式替换为另一个匹配模式

Replace one matched pattern with another in multiline text with sed

我有包含以下文本的文件:

mirrors:
  docker.io:
    endpoint:
      - "http://registry:5000"
  registry:5000:
    endpoint:
      - "http://registry:5000"
  localhost:
    endpoint:
      - "http://registry:5000"

我需要用 POSIX shell 脚本(不是 bash)中的这段文字替换它:

mirrors:
  docker.io:
    endpoint:
      - "http://docker.io"
  registry:5000:
    endpoint:
      - "http://registry:5000"
  localhost:
    endpoint:
      - "http://localhost"

替换应该在没有硬编码名称的所有地方动态完成。我的意思是我们应该从第一行 ("docker.io", "registry:5000", "localhost") 中取出子字符串,并用它替换第三行中的子字符串 "registry:5000"。

我找到了正则表达式,将其分为 5 组:(^ )([^ ]*)(:[^"]*"http:\/\/)([^"]*)(")

然后我尝试使用 sed 打印第 2 组而不是第 4 组,但这没有用:sed -n 's/\(^ \)\([^ ]*\)\(:[^"]*"http:\/\/\)\([^"]*\)\("\)//p'

请帮忙!

Awk 将是更好的选择,将要更改的字符串作为变量 str 和要更改的部分(“docker.io”或“localhost”或“registry:5000”传递) 所以:

awk -v findstr=" docker.io" -v str="http://docker.io" '
[=10=] ~ findstr { dockfound=1 # We have found the section passed in findstr and so we set the dockfound marker
             } 
/endpoint/ && dockfound==1 { # We encounter endpoint after the dockfound marker is set and so we set the found marker
               found=1;
               print;
               next 
              } 
 found==1 && dockfound==1 { # We know from the found and the dockfound markers being set that we need to process this line
               match([=10=],/^[[:space:]]+-[[:space:]]"/); # Match the start of the line to the beginning quote
               [=10=]=substr([=10=],RSTART,RLENGTH)str"\""; # Print the matched section followed by the replacement string (str) and the closing quote
               found=0; # Reset the markers
               dockfound=0 
               }1' file

一个班轮:

awk -v findstr=" docker.io" -v str="http://docker.io" '[=11=] ~ findstr { dockfound=1 } /endpoint/ && dockfound==1 { found=1;print;next } found==1 && dockfound==1 { match([=11=],/^[[:space:]]+-[[:space:]]"/);[=11=]=substr([=11=],RSTART,RLENGTH)str"\"";found=0;dockfound=0 }1' file

这可能对你有用 (GNU sed):

sed -E '1N;N;/\n.*endpoint:.*\n/s#((\S+):.*"http://)[^"]*##;P;D' file 

在文件中打开三行 window。

如果第二行包含endpoint:,则将http://之后的最后一段文字替换为:

之前的第一段文字

Print/Delete window 的第一行,然后通过追加下一行来补充三行 window。

重复直到文件结束。