[英]Replace multiline string with sed
I have a file that's basically an INI/CFG file the looks like this:我有一个基本上是 INI/CFG 文件的文件,如下所示:
[thing-a]
attribute1=foo
attribute2=bar
attribute3=foobar
attribute4=barfoo
[thing-b]
attribute1=dog
attribute3=foofoo
attribute4=castles
[thing-c]
attribute1=foo
attribute4=barfoo
[thing-d]
attribute1=123455
attribute2=dogs
attribute3=biscuits
attribute4=1234
Each 'thing' has a set of attributes that could include all the same ones or a subset there of.每个“事物”都有一组属性,可以包括所有相同的属性或其中的一个子集。
I am trying to write a small bash script that will replace the attributes for 'thing-c' with a predefined block $a1, $a2 & $a3 are generated elsewhere in the wider script:我正在尝试编写一个小的 bash 脚本,它将用预定义块替换“thing-c”的属性 $a1、$a2 和 $a3 在更广泛的脚本的其他地方生成:
NEW_BLOCK="[thing-c]
attribute1=${a1}
attribute2=${a2}
attribute3=${a3}"
I can find the right block with sed like this:我可以像这样找到带有 sed 的正确块:
THING_BLOCK=$(sed -nr "/^\[thing-c\]/ { :l /^\s*[^#].*/ p; n; /^\[/ q; b l; }" ./myThingFile)
I'm not sure if i've gone down a rabbit hole or what with this and I'm pretty sure there is a better way of doing it.我不确定我是不是掉进了兔子洞,或者这是怎么回事,我很确定有更好的方法可以做到这一点。
I'm wanting to do what is:我想做的是:
sed "s/${THING_BLOCK}/${NEW_BLOCK}/"
But I can't quite figure out the multiline aspect to this and I'm not sure what the best route to take is.但是我不太清楚这个的多线方面,我不确定最好的路线是什么。
Is there a way to do this sort of multiline find and replace with sed (or a better way with bash)有没有办法用 sed 进行这种多行查找和替换(或者使用 bash 的更好方法)
Is there a way to do this sort of multiline find and replace...
有没有办法进行这种多行查找和替换......
Yes there is indeed a better way, albeit using awk
:是的,确实有更好的方法,尽管使用
awk
:
awk -v blk="$NEW_BLOCK" -v RS= '{ORS = RT} $1 == "[thing-c]" {$0 = blk} 1' file
Using -v RS=
we use an empty record separator that splits records in input file on each new line.使用
-v RS=
我们使用一个空的记录分隔符,在每个新行上拆分输入文件中的记录。
Another awk. Store the replacement to file2
and:另一个 awk。将替换存储到
file2
并:
$ awk -v RS="" '
NR==FNR {
b=$0
next
}
$1~/thing-c/ {
$0=b
}
{
print (++c==1?"":ORS) $0
}' file2 file1
Output: Output:
[thing-a]
attribute1=foo
attribute2=bar
attribute3=foobar
attribute4=barfoo
[thing-b]
attribute1=dog
attribute3=foofoo
attribute4=castles
[thing-c]
attribute1=${a1}
attribute2=${a2}
attribute3=${a3}
[thing-d]
attribute1=123455
attribute2=dogs
attribute3=biscuits
attribute4=1234
When you want to use sed
(IMHO awk
is better here), you must have "nice" data (no special characters that sed
will try to handle and [
inside block thing-3
).当您想使用
sed
(恕我直言, awk
在这里更好)时,您必须拥有“不错”的数据(没有sed
将尝试处理的特殊字符和[
inside block thing-3
)。
I tested with我测试过
read -d '' -r NEW_BLOCK <<END
[thing-c]
attribute1=${a1}
attribute2=${a2}
attribute3=${a3}
END
For my solution I first need to replace newlines in $NEW_BLOCK
with the two characters \n
.对于我的解决方案,我首先需要用两个字符
\n
替换$NEW_BLOCK
中的换行符。
echo "This is the replacement string: ${NEW_BLOCK//$'\n'/\\n}"
With the "multi-line" option "-z" you can do使用“多行”选项“-z”你可以
sed -rz "s/\[thing-c\][^[]*/${NEW_BLOCK//$'\n'/\\n}\n\n/" myThingFile
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.