bash 在匹配文本块后使用 sed 插入一行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11183469/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
use sed to insert a line after matching a block of text
提问by tonytz
I try to use sed to insert a line after [Block B] in the following file:
我尝试使用 sed 在以下文件中的 [Block B] 之后插入一行:
[Block A]
line 1
line 2
[Block B]
line 1
line 2
[Block C]
line 1
line 2
The command I used:
我使用的命令:
sed '/\[Block B\]/,/^$/a\inserted line' file
The correct/desired result should be:
正确/期望的结果应该是:
[Block B]
line 1
line 2
inserted line
However, I got this instead:
但是,我得到了这个:
[Block B]
inserted line
line 1
inserted line
line 2
inserted line
Please tell me how I can get the desired result using sed. Thanks!
请告诉我如何使用 sed 获得所需的结果。谢谢!
回答by Paused until further notice.
sed -e '/\[Block B\]/{:a;n;/^$/!ba;i\inserted line' -e '}'
回答by starfry
I found this question while looking for a solution to my own problem, which was similar but a little different. I adapted the answers here to solve my problem.
我在寻找我自己的问题的解决方案时发现了这个问题,这个问题很相似但有点不同。我调整了这里的答案来解决我的问题。
I needed to insert some text at the end of a block inside a configuration file like this:
我需要在配置文件中的块末尾插入一些文本,如下所示:
name1 {
...
}
name2 {
...
inserted text line 1
inserted text line 2
}
name3 {
....
}
To achieve this I took @toyntz comment from above and adapted it thus:
为了实现这一点,我从上面引用了@toyntz 的评论并对其进行了调整:
/^name2 {/,/^}/{
/^}/i\ inserted text line 1
/^}/i\ inserted text line 2
}
That is just the sed expression; it can be put in a file and executed with sed -flike this:
那只是 sed 表达式;它可以放在一个文件中并sed -f像这样执行:
$ sed -f sed_expression data_file
This first expression searches for a range of lines starting with name2 {occurring at the beginning of a line and ending with }also occurring at the beginning of a line. That selects the block to work on. The remaining expression is enclosed in {curly braces}and operates on the selected range. It contains one command per line we wish to insert, each with an expression /^}/that matches the line with the closing curly brace followed by an insert ioperation to insert a line of text. The iis followed with a \so that leading whitespace is also inserted.
第一个表达式搜索以name2 {出现在行首并以}也出现在行首结束的一系列行。这将选择要处理的块。剩下的表达式用{大括号括起来,}并在选定的范围内进行运算。它包含我们希望插入的每一行一个命令,每个命令都有一个表达式/^}/,该表达式与带有右花括号的行匹配,然后是插入i操作以插入一行文本。在i随后一个\使领导空白也被插入。
I then took the expression a bit further, replacing the two insert commands with one:
然后我更进一步地表达了,用一个替换了两个插入命令:
/^name2 {/,/^}/{
/^}/i\
inserted text line 1\
inserted text line 2
}
Here the text to be inserted by one command is spread across the following two lines. Note the additional trailing \on the first line to continue the single command.
这里由一个命令插入的文本分布在以下两行中。注意\第一行的附加尾随以继续单个命令。
Next, I reduced it to one line. It makes it messy and harder to read but it still works:
接下来,我将其缩减为一行。它使它变得凌乱且难以阅读,但它仍然有效:
/^name2 {/,/^}/{/^}/i\ inserted text line 1\n inserted text line 2
}
The two lines to be inserted are separated by a newline \n. Astute readers will note that there are actually two lines there - you can't put the closing brace on the end of the first line; this is why the other answers above have a second -e expression. So, the above was the best I could do. To represent that on a bash command line:
要插入的两行由换行符分隔\n。细心的读者会注意到那里实际上有两行——你不能把右大括号放在第一行的末尾;这就是为什么上面的其他答案有第二个 -e 表达式。所以,以上是我能做的最好的。要在 bash 命令行上表示:
sed -e '/^name2 {/,/^}/{/^}/i\ inserted text line 1\n inserted text line 2' -e '}' data_file
I've written out this longhand in the hope that it explains to anyone looking to insert at the end of a block of text how a sed expression can be written to achieve that. Sed expressions can be quite cryptic and difficult to figure out - hopefully my explanations help in that regard.
我已经写下了这篇长篇大论,希望它能向希望在文本块末尾插入的任何人解释如何编写 sed 表达式来实现这一点。Sed 表达式可能非常神秘且难以理解 - 希望我的解释在这方面有所帮助。
回答by potong
This might work for you (GNU sed):
这可能对你有用(GNU sed):
sed '/^\[Block B\]/,/^$/!b;/^$/i\inserted line' file

