如何合并行(多行代码例程的)

如何合并行(多行代码例程的)

我有一个文件;内容如下:

cat -n /tmp/my_file

 1  verify(abc) {
 2    foo : bar;
 3    sub1(aa) {
 4    line1;
 5    } 
 6    sub2 (bb) {
 7    line1;
 8    // this line is a comment and must be ignored
 9    line2;
10       sub3 (cc) {
11       line1;
12     }
13    }  
14  }
15  
16  verify(efg) {
17    foo : bar;
18    sub1(aa) {
19    line1;
20    } 
21    sub2 (bb) {
22    line1;
23    // this line is a comment and must be ignored
24    line2;
25       sub3 (cc) {
26       line1;
27     }
28    }  
29  }

(行号仅供说明之用,不属于文件的一部分。)

我需要使用 awk 或 Perl 将其内容转换为以下格式:

verify(abc) { foo : bar; sub1 (aa) { line1; } sub2 (bb) { line1; line2; sub3 (cc) { line1; } } }

verify(efg) { foo : bar; sub1 (aa) { line1; } sub2 (bb) { line1; line2; sub3 (cc) { line1; } } }

我怎样才能做到这一点?

答案1

一行:

awk '{ if ( NF > 0 && $1 !~ /^\/\// ) { bl=0; for (i=1;i<=NF;i++) printf "%s ", $i; }; if ( NF == 0 && bl == 1 ) {printf "\n" }; if ( NF == 0 && bl == 0 ) {bl=1; printf "\n\n" } } END { if ( bl == 0 ) { printf "\n" } } ' /tmp/my_file

解释:

if ( NF > 0 && $1 !~ /^\/\// ) { bl=0; for (i=1;i<=NF;i++) printf "%s ", $i; }

如果字段数大于 0 并且第一个字段不是注释,则为每个字段打印该字段和一个空格。正则表达式实际上是“^//”(以“//”开头),但是“/”必须转义,因此“\/”。另外 bl=0 设置先前的空行标志,我们将使用它来控制语句中稍后的记录/空行句柄的结束。

接下来,处理空行/记录结束的情况;

首先,检查这是否只是一个空行。

if ( NF == 0 && bl == 1 ) {printf "\n" };

如果字段数为 0 并且设置了先前的空行标志,则只需打印一个换行符。

接下来,测试一下我们是否刚刚结束一行数据/文本并需要添加一行

if ( NF == 0 && bl == 0 ) {bl=1; printf "\n\n" }

如果字段数为 0 并且未设置先前的空行标志,则设置空行标志并打印行结尾。

最后!!!

END { if ( bl == 0 ) { printf "\n" } }

如果我们完成了文件,请查看是否打印了记录行结束符,如果没有则打印。

答案2

假设每个块(每个“verify()”例程)以一行开头,verify 并以一行开头} (并且没有行之内例程以}) 开头,并且空白都是空格:

前任

printf '%s\n' 'g|^ *//|d' 'g/^verify/.,/^}/j' x | ex -- /tmp/my_file

ex使用(命令行版本vi /  )编辑文件vim

  • g|^ *//|d查找与正则表达式匹配的所有行^ *// (即,包含//零个或多个空格,但没有其他内容)并将其删除。
  • g/^verify/.,/^}/j查找与正则表达式匹配的每一行 ^verify(即以 开头 verify)。然后,对于每个,找到与正则表达式匹配的第一行^} (即以 开头 }),并且 jverifyoins和 之间的所有行}(包含在内),丢弃被挤出的换行符之前和之后的额外空格。
  • x保存并退出。
    笔记:这将覆盖输入文件。

sed

sed -n '/^verify/ { h; d }; /^ *\/\//d; /./H; /^}/ { g; s/ *\n */ /gp }; /^$/p' /tmp/my_file
  • -n— 除非被告知,否则不要打印。
  • /^verify/ { h; d }— 当您看到以 开头的行时verify,将其复制到H旧空间和d删除模式空间(即,继续到下一个输入行而不进行任何进一步的处理)。
  • /^ *\/\//d— 当您看到以零个或多个空格开头的行 和 时//,请将其删除(即,继续到下一个输入行而不进行任何进一步处理)。
  • /./H— 对于上述以外的任何非空行,将其附加到保留空间。
  • /^}/ { g; s/ *\n */ /gp }— 当您看到以 开头的行时}G将保持空间设置到模式空间中。然后通过用单个空格替换每个嵌入的换行符(以及前面和后面的空格)将其压缩为一行,然后打印它。
  • /^$/p— 打印空行。

awk

awk '
    /^ *\/\//   { next; }
    /./         { buffer = buffer " " $0; }
    /^}/        { sub(/^ */, "", buffer); sub(/ *$/, "", buffer);
                  gsub(/ * /, " ", buffer); print buffer; buffer = ""; }
    /^$/        { print; }
    ' /tmp/my_file
  • 当您看到评论时,请跳过它。
  • 将所有其他非空白行连接到buffer.换行符被隐式丢弃。
  • 当您看到以 开头的行时},删除 中所有多余的空格buffer,打印它并清除它。
  • 打印空行。

相关内容