如何使用sed匹配)\ n {?

时间:2019-01-16 14:55:41

标签: bash shell sed glob metacharacters

我需要编写一个shell脚本,该脚本将以非常复杂的模式匹配后在.c文件中输入一个字符串。

模式为:)\n{

\n{之间没有任何制表符/空格。就是说,我想与位于文件第一列的{匹配(这仅是为了与C中的函数声明之后的)\n{匹配,而不是与循环或条件之后的声明匹配) 。

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

很高兴听到您对此事的建议。

4 个答案:

答案 0 :(得分:2)

您应该避免使用sed,它是基于行的工具,不会很好地处理此类任务。

如果您坚持使用sed并且正在使用GNU sed,则可以使用-z / --null-data选项,该选项将一次读取整个文件(读取NUL字节分隔的记录而不是换行分隔的记录),这将使您能够像预期的那样使用)\n{模式:

$ { echo "line1)"; echo "{line2"; } | sed -z 's/)\n{/X/g'
line1Xline2

由于这需要将整个文件加载到内存中,因此预期大型文件的性能会很差。


如果您喜欢无法维护的乱语,可以使用sed鲜为人知的PtD命令解决此问题:

sed '/)$/{N;s/)\n{/) {\n\ttime_exe(__func__, cl(clock()));/;t;P;D}'

Try it here !

这是通过在遇到以N结尾的行时在模式空间()中加载另一行,尝试替换两行模式,然后打印({{1 }}),如果模式不匹配,则从模式空间中删除(P)第一行(否则D分支到下一个迭代),将模式空间中的第二行保留为用作下一次迭代的第一行。

使用t通常是足够好的,但是它可能会失败,因为/first line pattern/{N;s/whole pattern/replacement/}将消耗您不会测试第一行模式的行。 here对此进行了说明。

答案 1 :(得分:2)

我同意@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
  • 组成

答案 2 :(得分:0)

这可能对您有用(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

答案 3 :(得分:0)

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;

    //
}

由于将整个文件读入内存,因此与Aaron's answer相同。