使用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。
重复直到文件结束。
我有包含以下文本的文件:
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。
重复直到文件结束。