我发布了this question,有人回复了这个
sed '/^void.*{$/!b;:a;/\n}$/bb;$!{N;ba};:b;s/\n/&test1&/;s/\(.*\n\)\(.*\n\)/\1test2\n\2/' file
我是sed和regex的新手,我无法理解每个部分的功能。
我将尝试解释我所理解的内容,你们可以填补遗漏的内容。我会按角色去角色
^void.*{$
- 这意味着以void
开头并以{
/!b;
我没有得到它的作用。现在b
适用于branching
。什么是/
在那里做什么:a;
用于制作标签a
/\n
再次没有理解/
那里}$
结尾的}
/bb
我不明白$!
表示如果不是文件结尾{N;
没有得到它的意思,N意味着复制缓冲区中的下一行,但确实得到{
:b
没有得到它。 b用于分支,但不知道它在那里做什么
10。s/\n/&test1&/
我认为用\ntest1\n
取代\ n但不确定s/\(.*\n\)\(.*\n\)/\1test2\n\2/
也不会得到这个答案 0 :(得分:2)
这个词:
/^void.*{$/!b
表示匹配^void.*{$
,斜杠是正则表达式周围的正则表达式分隔符。所以你得到/^void.*{$/
。如果在/regex/!
中跟随匹配表达式后出现感叹号,则表示如果正则表达式not
匹配,则执行以下命令。以下命令是b
,它是分支。其中没有标签名称,在脚本末尾分支。总的来说,这个表达式尝试匹配^void.*{$
(即,以void开头并以{
结尾的行)并跳过(b
)脚本的其余部分,以防匹配失败({ {1}})。
这件事:
!
启动标签:a;/\n}$/bb;$!{N;ba};
并尝试匹配:a;
(换行符和一行\n}$
),该行再次包含在}
中。在匹配时,它将(/regex/
)分支到标签b(因此,b
)。如果这不是输入的结尾(/regex/bb
),则读取行$!
并跳回标签a(N
)。这里的卷曲对(即ba
)创建一个块。这个块
如果{commands}
为真,则作为一个整体执行,这意味着有更多的输入。所以$!
只是意味着:
$!{N;ba}
答案 1 :(得分:2)
您可以将多个sed表达式与;
字符链接在一起。以下分别介绍每一个。
第一个表达式/^void.*{$/!b
在分隔/
&#39}之间有一个匹配器表达式。匹配:
^
- 行的开头
void
- 后跟字符" void"
.*
- 后跟任何内容
{
- 后面是左卷曲
$
- 接着是行尾
第一个表达式中的修饰符!b
表示如果匹配器不匹配,则中止sed评估。
:a
表达式是一个标签。它与类似goto的sed功能一起使用,称为分支。我们将在下一个表达式中看到标签的使用方式。
表达式/\n}$/bb
匹配:
\n
- 换行符
}
- 接着是右卷曲
$
- 接着是行尾
修饰符bb
表示如果找到匹配项,"分支"到标签b。标签b在后面的表达式中定义为:b
。
$!{N;ba}
表达式应该读作一个,即使它在中间有一个;
。在这种情况下,curlies代表了一系列旨在一起执行的命令。
$!
- 如果它不是输入的结尾
{
- 启动一组命令(在这种情况下,有两个命令)
N
- 默默地读另一行
ba
- 分支标记
}
- 结束命令组
接下来是标签:b
,当我们通过}
表达式匹配单行/\n}$/bb
时,我们会点击该标签。
最后有两种替代模式,它们都是非常标准的正则表达式。表达式之前的s
实际上意味着s/find_this/replace_it_with_this/
。在s/\n/&test1&/
的情况下,我们有:
\n
- 找到换行符
/
- 并将其替换为
&
- 在第一个表达式中匹配的东西(在本例中为换行符)
test1
- 单词test1
&
- 再次匹配的东西
所以基本上s/\n/&test1&/
表示将\n
替换为\ntest1\n
。
最后一个表达式类似,但引入了一些称为捕获的东西。 Captures让你仍然可以匹配所有内容,但保留\(
和\)
之间的所有内容,以便在表达式的替换部分中使用。例如,如果给出s/a\(b\)c\(d\)e/\1 \2/
的输入字符串,b d
将输出abcde
。在示例中,\1
和\2
将替换为转义的parens b
和d
中分别捕获的内容。
s
- 这是替换模式:
/
- 找到
\(
- 并放入\1
替换变量
.
- 任何事情
*
- 及其任何数量
\n
- 包括您遇到的第一个换行符
\)
- (\1
的捕获结束)
\(
- 并放入\2
替换变量
.
- 任何事情
*
- 及其任何数量
\n
- 包括您遇到的第一个换行符
\)
- (\2
的捕获结束)
/
- 并用
\1
- 捕获的第一件事,
test2\n
- test2 \ n,
\2
- 第二件事就是抓住了。