如何匹配 )\n{ 使用 sed?
How to match )\n{ using sed?
我需要编写一个 shell 脚本,它会在我的 .c 文件中输入一个字符串来匹配一个相当复杂的模式。
模式为:)\n{
、
\n
和 {
之间没有任何 tabs/spaces。这就是说我想匹配位于我文件第一列的 {
(这是为了只匹配 )\n{
在 C 中的函数声明之后,而不是在循环或条件之后的那些) .
void some_function_declaration(char var1, char var2)
{
我已经阅读了手册、论坛,但仍然无法找到编写模式以匹配或找到相应正则表达式的正确方法。相应的输出将是:
void some_function_declaration(char var1, char var2)
{ time_exe(__func__, cl(clock()));
rest of the function...
以下是我到目前为止想出但行不通的方法。
尝试 1
sed -i '' '/)$\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c
尝试 2
sed -i '' '/)\n{ /a time_exe(__func__, cl(clock()));' >> list_func2.c
尝试 3
sed -i '' '/)/\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c
很高兴听到您对此事的建议。
您应该避免使用 sed
,这是一种基于行的工具,无法很好地处理此类任务。
如果您坚持使用 sed
并且正在使用 GNU sed
,您可以使用 -z
/ --null-data
选项,这将一次读取整个文件(读取 NUL 字节分隔的记录而不是换行分隔的记录)并且将使您能够像您期望的那样使用 )\n{
模式:
$ { echo "line1)"; echo "{line2"; } | sed -z 's/)\n{/X/g'
line1Xline2
由于这需要将整个文件加载到内存中,预计大文件的性能会很差。
如果你喜欢无法维护的乱码,你可以使用 sed
鲜为人知的 P
、t
和 D
命令来解决这个问题:
sed '/)$/{N;s/)\n{/) {\n\ttime_exe(__func__, cl(clock()));/;t;P;D}'
这通过在遇到以 )
结尾的行时在模式 space (N
) 中加载额外的行来工作,尝试替换两行模式,如果模式不匹配,则打印 (P
) 并删除 (D
) 模式 space 的第一行(否则 t
分支到下一次迭代),将模式 space 中的第二行保留为下一次迭代的第一行。
使用 /first line pattern/{N;s/whole pattern/replacement/}
通常就足够了,但它可能会失败,因为 N
会占用您不会测试第一行模式的行。这是说明 here.
我同意@Aaron 的观点,但如果你仍然想要 sed
,请看这个:
$ cat /tmp/del.txt
void some_function_declaration(char var1, char var2)
{
...
}
void enother_function_declaration(char var1, char var2)
{
...
}
并应用 sed
:
$ cat /tmp/del.txt | sed ':a;N;$!ba;s/)\n{/)\{\ntime_exe(__func__, cl(clock()));/g'
void some_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
...
}
void enother_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
...
}
我觉得这看起来像你想要的
UPD
让我解释一下..
更多的跨平台兼容语法是:
sed -e ':a' -e 'N' -e'$!ba' -e 's/)\n{/)\n{ ... ;/g'
哪里
':a'
- 创建一个分支标签(命名为a
),稍后可以返回
'N'
- 将下一行附加到当前行(中间有 \n
)
'$!ba'
- 如果下一行是最后一行 ,则跳转到标签a
's/)\n{/)\n{ ... ;/g'
- 在单行中进行 global 替换,由所有行和 \n
s 组成
这可能适合您 (GNU sed):
sed ':a;/)$/!b;n;/^{/!ba;c{ time_exe(__func__, cl(clock()));' file
如果当前行不以 )
结尾,则中断 sed 的任何进一步处理。否则,打印当前行并读入下一行。如果该行不是以 {
从头检查,否则将其更改为所需格式。
也可以附加或插入所需的格式,见下文:
sed ':a;/)$/!b;n;/^{/!ba;a{ time_exe(__func__, cl(clock()));' file
或者,
sed ':a;/)$/!b;n;s/^{/& time_exe(__func__, cl(clock()));/;Ta' file
Perl 可用于此:
$ cat file.c
void some_function_declaration(char var1, char var2)
{
if (a)
{ b; }
}
void func2()
{
//
}
$ perl -0777 -pe 's {\)\n\{} {$& some other stuff;\n}g' file.c
void some_function_declaration(char var1, char var2)
{ some other stuff;
if (a)
{ b; }
}
void func2()
{ some other stuff;
//
}
由于将整个文件读入内存,所以与 相同。
我需要编写一个 shell 脚本,它会在我的 .c 文件中输入一个字符串来匹配一个相当复杂的模式。
模式为:)\n{
、
\n
和 {
之间没有任何 tabs/spaces。这就是说我想匹配位于我文件第一列的 {
(这是为了只匹配 )\n{
在 C 中的函数声明之后,而不是在循环或条件之后的那些) .
void some_function_declaration(char var1, char var2)
{
我已经阅读了手册、论坛,但仍然无法找到编写模式以匹配或找到相应正则表达式的正确方法。相应的输出将是:
void some_function_declaration(char var1, char var2)
{ time_exe(__func__, cl(clock()));
rest of the function...
以下是我到目前为止想出但行不通的方法。
尝试 1
sed -i '' '/)$\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c
尝试 2
sed -i '' '/)\n{ /a time_exe(__func__, cl(clock()));' >> list_func2.c
尝试 3
sed -i '' '/)/\n{/a time_exe(__func__, cl(clock()));' >> list_func2.c
很高兴听到您对此事的建议。
您应该避免使用 sed
,这是一种基于行的工具,无法很好地处理此类任务。
如果您坚持使用 sed
并且正在使用 GNU sed
,您可以使用 -z
/ --null-data
选项,这将一次读取整个文件(读取 NUL 字节分隔的记录而不是换行分隔的记录)并且将使您能够像您期望的那样使用 )\n{
模式:
$ { echo "line1)"; echo "{line2"; } | sed -z 's/)\n{/X/g'
line1Xline2
由于这需要将整个文件加载到内存中,预计大文件的性能会很差。
如果你喜欢无法维护的乱码,你可以使用 sed
鲜为人知的 P
、t
和 D
命令来解决这个问题:
sed '/)$/{N;s/)\n{/) {\n\ttime_exe(__func__, cl(clock()));/;t;P;D}'
这通过在遇到以 )
结尾的行时在模式 space (N
) 中加载额外的行来工作,尝试替换两行模式,如果模式不匹配,则打印 (P
) 并删除 (D
) 模式 space 的第一行(否则 t
分支到下一次迭代),将模式 space 中的第二行保留为下一次迭代的第一行。
使用 /first line pattern/{N;s/whole pattern/replacement/}
通常就足够了,但它可能会失败,因为 N
会占用您不会测试第一行模式的行。这是说明 here.
我同意@Aaron 的观点,但如果你仍然想要 sed
,请看这个:
$ cat /tmp/del.txt
void some_function_declaration(char var1, char var2)
{
...
}
void enother_function_declaration(char var1, char var2)
{
...
}
并应用 sed
:
$ cat /tmp/del.txt | sed ':a;N;$!ba;s/)\n{/)\{\ntime_exe(__func__, cl(clock()));/g'
void some_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
...
}
void enother_function_declaration(char var1, char var2){
time_exe(__func__, cl(clock()));
...
}
我觉得这看起来像你想要的
UPD
让我解释一下..
更多的跨平台兼容语法是:
sed -e ':a' -e 'N' -e'$!ba' -e 's/)\n{/)\n{ ... ;/g'
哪里
':a'
- 创建一个分支标签(命名为a
),稍后可以返回'N'
- 将下一行附加到当前行(中间有\n
)'$!ba'
- 如果下一行是最后一行 ,则跳转到标签's/)\n{/)\n{ ... ;/g'
- 在单行中进行 global 替换,由所有行和\n
s 组成
a
这可能适合您 (GNU sed):
sed ':a;/)$/!b;n;/^{/!ba;c{ time_exe(__func__, cl(clock()));' file
如果当前行不以 )
结尾,则中断 sed 的任何进一步处理。否则,打印当前行并读入下一行。如果该行不是以 {
从头检查,否则将其更改为所需格式。
也可以附加或插入所需的格式,见下文:
sed ':a;/)$/!b;n;/^{/!ba;a{ time_exe(__func__, cl(clock()));' file
或者,
sed ':a;/)$/!b;n;s/^{/& time_exe(__func__, cl(clock()));/;Ta' file
Perl 可用于此:
$ cat file.c
void some_function_declaration(char var1, char var2)
{
if (a)
{ b; }
}
void func2()
{
//
}
$ perl -0777 -pe 's {\)\n\{} {$& some other stuff;\n}g' file.c
void some_function_declaration(char var1, char var2)
{ some other stuff;
if (a)
{ b; }
}
void func2()
{ some other stuff;
//
}
由于将整个文件读入内存,所以与