1

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

模式是:)\n{,

\n和之间没有任何制表符/空格{。也就是说,我想与{位于文件第一列中的 a 匹配(这是为了仅与)\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

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

4

4 回答 4

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'-在单行中进行全局\n替换,由所有行和s组成
于 2019-01-16T15:29:49.033 回答
2

您应该避免使用sedwhich 是基于行的工具,并且不能很好地处理此类任务。

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

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

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


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

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

在这里试试!

这通过在遇到以N结尾的行时在模式空间( ' 不匹配(否则分支到下一次迭代),将模式空间中的第二行留作下一次迭代的第一行。)PDt

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

于 2019-01-16T15:21:19.830 回答
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 的回答相同。

于 2019-01-16T16:09:41.833 回答
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
于 2019-01-16T15:52:17.787 回答