如何使用awk过滤文件的整个块?

时间:2018-03-31 07:24:08

标签: awk gawk

示例输入:

void foo(void) {
  printf("hello\n");
}

// Split
void noon(void) {
  printf("lunch\n");
}

void bye(void) {
  printf("goodbye\n");
}

我想过滤掉以// Split开头的所有块:

void foo(void) {
  printf("hello\n");
}

void bye(void) {
  printf("goodbye\n");
}

或仅过滤那些块:

// Split
void noon(void) {
  printf("lunch\n");
}

我该怎么做?基本上,只要它看到“// Split”,该行和将来的输出就会指向第二个文件。每当它看到一行以“}”开头时,它应该正常输出该行,但是未来的输出将被定向回第一个文件。

5 个答案:

答案 0 :(得分:1)

如果您的实际Input_file与显示的示例相同,那么以下内容可能对您有所帮助。

awk '/\/\/ Split/{non_flag=1} !non_flag; /}/ && non_flag{non_flag=""}' Input_file

如果您想要打印包含split的块,那么以下内容可能对您有帮助。

awk '/\/\/ Split/{flag=1} flag;  /}/ && flag{flag=""}'  Input_file

答案 1 :(得分:1)

您可以像这样替换输出文件:

awk '
    BEGIN {
        f=F[0]="ofile1"
        F[1]="ofile2"
    }
    /^[/][/] *Split/ || (c && /^}$/) {
        f=F[c=!c]
    }
    { print > f }
' inputs...

如果你只想要任何一个部分,你可以使打印块以c为条件并摆脱fF

答案 2 :(得分:1)

$ awk -v RS= -v ORS='\n\n' '/^\/\/ Split/' file
// Split
void noon(void) {
  printf("lunch\n");
}

$ awk -v RS= -v ORS='\n\n' '!/^\/\/ Split/' file
void foo(void) {
  printf("hello\n");
}

void bye(void) {
  printf("goodbye\n");
}

要将“Split”块重定向到名为“splits”的新文件,并将其余部分打印到stdout,将使用GNU awk或mawk(可能还有其他一些):

awk -v RS= -v ORS='\n\n' '
    { print > (/^\/\/ Split/ ? "splits" : "/dev/stdout") }
' file

或与任何awk:

awk -v RS= -v ORS='\n\n' '
    { out = (/^\/\/ Split/ ? "splits" : "") }
    out { print > out; next }
    { print }
' file

答案 3 :(得分:0)

这两种情况都有一个 awk 命令(假设没有嵌套语句function { ... { ... } ... }):

awk -v pr_split=1 \
'/^\/\/ Split/{ f = 1; n = NR }
 NR != n+1 && /.+ {/{ f = 0 }
 f && pr_split;
 !pr_split{ if (f) next; else print }' file
  • pr_split - 变量,代表“print split”部分。告知是否仅打印// Split部分或除了那些之外的所有部分

仅打印// Split个部分:

awk -v pr_split=1 ...

输出:

// Split
void noon(void) {
  printf("lunch\n");
}

打印除// Split部分以外的所有内容:

awk -v pr_split=0 ...

输出:

void foo(void) {
  printf("hello\n");
}

void bye(void) {
  printf("goodbye\n");
}

答案 4 :(得分:0)

如果只在评论中出现“拆分”:

$ awk -v RS= '/Split/' file
// Split
void noon(void) {
  printf("lunch\n");
}

更冗长,但更准确:

awk -F'\n' -v RS= '$1 ~ /Split/' file

当记录分隔符为空时,每个记录都用空行分隔。