我有一个这样的文件:
x = {
y = {
z = {
block = {
line1
line2
line3
}
}
}
}
x2 = {
y2 = {
block = {
line4
line5
}
}
}
xyz
block = {
line6
}
等等。我需要反转块内的行,但其他所有内容都应保持顺序,如下所示:
x = {
y = {
z = {
block = {
line3
line2
line1
}
}
}
}
x2 = {
y2 = {
block = {
line5
line4
}
}
}
xyz
block = {
line6
}
如何使用 sed 或 awk 做到这一点?我设法将这些块颠倒过来,但无法将它们放回原位:
sed -n '/block = {.$/,/}$/p' inputfile | tac
答案1
如果你对 Perl 没问题:
perl -ne 'if($f && /}/){$f=0; print @blk};
$f ? unshift(@blk, $_) : print;
if(/block = {/){$f=1; @blk=()}' ip.txt
if(/block = {/){$f=1; @blk=()}
如果输入行包含,则初始化@blk
数组并设置标志$f
block = {
$f ? unshift(@blk, $_) : print
如果该标志处于活动状态,则在数组的前面插入输入行@blk
,否则打印输入行if($f && /}/){$f=0; print @blk}
如果该标志处于活动状态并且输入行包含,则取消设置该标志并打印数组}
的内容@blk
和awk
:
awk 'f && /}/{f=0; for(i=c; i>=1; i--) print blk[i]}
{if(f) blk[++c] = $0; else print}
/block = {/{f=1; c=0}' ip.txt
答案2
另一种perl
方法,依靠缩进来找到}
相应的结束block = {
:
perl -C -0777 -pe '
s{^(\h*)block = \{\n\K.*?\n(?=\1\}$)}{
join "", reverse $& =~ m{.*\n}g
}gems' < your-file
答案3
证明sed
代码可以很容易编写,但很难阅读:
sed '/block = {/,/}/{/[{}]/!{G;h;d;};x;s/.$//p;g;s/.*//;x;}' file
这个概念是通过附加当前的保留空间来收集保留空间中要反转的行(没有大括号的行)(因此顺序会自动更改)。该代码是可移植的,可与任何sed
实现一起使用。详细地:
/block = {/,/}/
block = {
选择从到下一个 的每个范围}
,就像您自己所做的那样。所有其他类似的代码xyz
均不加更改地打印/[{}]/!{G;h;d;}
处理不带大括号的行(块行):G
附加当前保留空间,h
将结果移动到保留空间并d
停止处理带有输出的该行- 其余部分仅针对支撑线执行。这就是需要通过
x
更改缓冲区来打印保留空间中的行的地方,然后s/.$//p
删除通过附加到空保留空间而引入的保留空间中的尾随换行符。 ubstitude 命令p
的选项仅s
在成功替换时打印,以避免打印空的保留空间。最后用于g
从保留空间恢复当前行 - 最后我们需要清空保持空间:
s/.*//;x
:将当前行保存到h
旧空间,清空模式空间和交换缓冲区,因此保持空间将是空的,而模式空间再次包含当前行以进行输出。
答案4
使用乐(以前称为 Perl_6)
~$ raku -ne 'BEGIN my @blk; if (/block/ && .put) { for lines() {
if /\}/ { put join "\n", (@blk.pop xx @blk.elems, $_); last};
@blk.push: $_ }
} else { .put };' file
#OR (more simply)
~$ raku -ne 'BEGIN my @blk; if (/block/ & .put) { for lines() {
if /\}/ { .put for (@blk.pop xx @blk.elems, $_).flat; last};
@blk.push: $_ }
};' file
上面的代码是用 Raku(一种 Perl 家族语言)编写的。使用-ne
非自动打印标志逐行读取输入。在BEGIN
块内,@blk
声明一个数组,if
遇到“块”字符串(关键字),lines
并读取到最后的}
右花括号。当它们被读取时,lines
被push
编辑到@blk
数组中,并在找到结束 Curliepop
时完全关闭(即以相反的顺序)。}
last
输入示例:
x = {
y = {
z = {
block = {
line1
line2
line3
}
}
}
}
x2 = {
y2 = {
block = {
line4
line5
}
}
}
xyz
block = {
line6
}
示例输出:
x = {
y = {
z = {
block = {
line3
line2
line1
}
}
}
}
x2 = {
y2 = {
block = {
line5
line4
}
}
}
xyz
block = {
line6
}
附录:对于任何寻求 @Sundeep 优秀 Perl5 解决方案的 Raku 翻译的人来说,这里是:
~$ raku -ne 'BEGIN my @blk; state $f;
if ($f && /\}/) {$f=0; .put for @blk};
$f ?? unshift(@blk, $_) !! .put;
if (/block/) {$f=1; @blk=()};' file