英文:
how to get sed affect only the first matched range
问题
这是您要翻译的内容:
我正在使用这个sed命令
sed -i "/^### Header$/,/^### [^#]*$/{//!d}"
这个sed命令会删除从Header到Header 2之间的所有文本。
我只想删除第一个匹配范围内的文本。
请注意,我不知道下一个Header的标题是什么!
输入:
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
输出:
### Header
### Header 2
some text
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
如果您需要进一步的帮助,请随时提出。
英文:
I am using this sed
sed -i "/^### Header$/,/^### [^#]*$/{//!d}"
This sed deleted all the text between Header to Header 2.
I want only to delete the text for the first matched range.
Note I don't know what is the title of the next Header!
Input:
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
output:
### Header
### Header 2
some text
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
答案1
得分: 3
使用 GNU `sed`
$ sed '/^### Header$/,/^###/{1,/^###/{//!d}}' input_file
Header
Header 2
some text
Header
blabla
Header 2
some text
Header
blabla
Header 2
some text
<details>
<summary>英文:</summary>
Using GNU `sed`
$ sed '/^### Header$/,/^###/{1,/^###/{//!d}}' input_file
Header
Header 2
some text
Header
blabla
Header 2
some text
Header
blabla
Header 2
some text
</details>
# 答案2
**得分**: 0
sed 是在简单字符串上进行 s/old/new/ 替换的优秀工具,对于其他情况,只需使用 awk 来结合清晰度、可移植性、健壮性、效率等方面。在这种情况下,在任何 Unix 系统上的任何 shell 中使用任何 awk:
$ awk '/^### [^#]/{inRange=0} !inRange{print} /^### Header$/ && (++cnt==1){inRange=1}' file
Header
Header 2
一些文本
Header
blabla
Header 2
一些文本
Header
blabla
Header 2
一些文本
请注意,通过使用一个标志变量 `inRange`,你无需测试范围的开始或结束两次,这在使用范围运算符时很常见,参见 https://stackoverflow.com/questions/23934486/is-a-start-end-range-expression-ever-useful-in-awk。通过使用计数器变量 `cnt`,你可以轻松修改代码,使其操作于范围的第二个、第十个或其他任何出现,而不仅仅是第一次出现。sed 没有变量。
<details>
<summary>英文:</summary>
sed is an excellent tool for doing s/old/new/ on simple strings, for anything else just use awk for some combination of clarity, portability, robustness, efficiency, etc. In this case, using any awk in any shell on every Unix box:
$ awk '/^### [^#]/{inRange=0} !inRange{print} /^### Header$/ && (++cnt==1){inRange=1}' file
### Header
### Header 2
some text
### Header
blabla
### Header 2
some text
### Header
blabla
### Header 2
some text
Note that by using a flag variable `inRange` you don't have to test the start or end of the range twice as is common if you use a range operator, see https://stackoverflow.com/questions/23934486/is-a-start-end-range-expression-ever-useful-in-awk, and by using a counter variable `cnt` you could trivially change the code to operate on the 2nd or 10th or any other occurrence of the range instead of or in addition to the first occurrence. sed doesn't have variables.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论