我有一个文件;内容如下:
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
)。然后,对于每个,找到与正则表达式匹配的第一行^}
(即以 开头}
),并且 jverify
oins和 之间的所有行}
(包含在内),丢弃被挤出的换行符之前和之后的额外空格。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
,打印它并清除它。 - 打印空行。