如何使用 awk 过滤文件的整个块?
How to use awk to filter entire blocks of a file?
示例输入:
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”,该行和以后的输出就会指向第二个文件。每当它看到以“}”开头的行时,它应该正常输出该行,但以后的输出将被定向回第一个文件。
如果您的实际 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
两种情况都有一个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");
}
您可以像这样交替输出文件:
awk '
BEGIN {
f=F[0]="ofile1"
F[1]="ofile2"
}
/^[/][/] *Split/ || (c && /^}$/) {
f=F[c=!c]
}
{ print > f }
' inputs...
如果您只想要任何一个部分,您可以使打印块以 c
为条件并删除 f
和 F
。
如果"Split"只出现在评论中:
$ awk -v RS= '/Split/' file
// Split
void noon(void) {
printf("lunch\n");
}
有点冗长,但更准确:
awk -F'\n' -v RS= ' ~ /Split/' file
当记录分隔符为空时,每条记录由空行分隔。
$ 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" 的新文件并将其余部分打印到标准输出,可以使用 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
示例输入:
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”,该行和以后的输出就会指向第二个文件。每当它看到以“}”开头的行时,它应该正常输出该行,但以后的输出将被定向回第一个文件。
如果您的实际 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
两种情况都有一个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");
}
您可以像这样交替输出文件:
awk '
BEGIN {
f=F[0]="ofile1"
F[1]="ofile2"
}
/^[/][/] *Split/ || (c && /^}$/) {
f=F[c=!c]
}
{ print > f }
' inputs...
如果您只想要任何一个部分,您可以使打印块以 c
为条件并删除 f
和 F
。
如果"Split"只出现在评论中:
$ awk -v RS= '/Split/' file
// Split
void noon(void) {
printf("lunch\n");
}
有点冗长,但更准确:
awk -F'\n' -v RS= ' ~ /Split/' file
当记录分隔符为空时,每条记录由空行分隔。
$ 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" 的新文件并将其余部分打印到标准输出,可以使用 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