我试图在一个冗长的文件(input.txt)中搜索一个关键字(cell(edita)),该文件具有10000行以上的行以及不同的单元格名称,例如cell(noedit),cell(editb)。然后我应该搜索对于插针(q)(第二次出现)并添加行“ class”,插针(yz)(第二次出现)并添加“木板”。 我不应该操纵单元格(noedit)块。
我的input.txt
cell (edita) {
test{
pin (Q) {
zzzzzz
}
pin (yz) {
zzzzz
}
}
pin (Q) {
add
}
pin (yz) {
add
}
}
cell (noedit) {
test{
pin (Q) {
zzzzzz
}
pin (yz) {
zzzzz
}
}
pin (Q) {
add
}
pin (yz) {
add
}
}
cell (editb) {
test{
pin (Q) {
zzzzzz
}
pin (yz) {
zzzzz
}
}
pin (Q) {
add
}
pin (yz) {
add
}
}
我的output.txt应该看起来像这样
cell (edita) {
test{
pin (Q) {
zzzzzz
}
pin (yz) {
zzzzz
}
}
pin (Q) {
"class";
add
}
pin (yz) {
board;
add
}
}
cell (noedit) {
test{
pin (Q) {
zzzzzz
}
pin (yz) {
zzzzz
}
}
pin (Q) {
add
}
pin (yz) {
add
}
}
cell (editb) {
test{
pin (Q) {
zzzzzz
}
pin (yz) {
zzzzz
}
}
pin (Q) {
"class";
add
}
pin (yz) {
board ;
add
}
}
我尝试编写sed,仅当文件来自pin时(即,没有单元格(a)行),甚至只操纵第二次出现
sed'/\spin\s(Q)/{p;s/./1/;H;g;/^(\n1){2}$/s// class; / p; d}'input.txt sed'/\spin\s(y)/{p;s/./1/;H;g;/^(\n1){2}$/s//板; / p; d}'input.txt
请任何人帮我寻找细胞然后进行操纵。
预先感谢
答案 0 :(得分:1)
关于perl的idk,但sed用于做s / old / new 全部,而对于其他任何标准UNIX工具来说,awk都是为了清晰,简单,高效,可移植性等。从您的示例中可以看出,这就是您要做的所有事情:
$ cat tst.awk
BEGIN {
map["pin (Q)"] = "class ;"
map["pin (y)"] = "board ;"
}
{ print }
$1 == "cell" { cell = "$2" }
cell == "(a)" {
for (pin in map) {
if ( (s=index($0,pin)) && (++cnt[pin]==2) ) {
print substr($0,1,s-1) map[pin]
}
}
}
$ awk -f tst.awk file
cell (a) {
test{
pin (Q) {
zzzzzz
}
pin (y) {
zzzzz
}
}
pin (Q) {
class ;
add
}
pin (y) {
board ;
add
}
}
如果不是,那么请编辑您的问题以阐明您的要求并提供更真实的示例输入输出。
从您在@potong答案下的评论中可以看到,您想添加第3个针脚-为此,您只需在现有2个map[]
分配下添加新映射即可。
BEGIN {
map["pin (Q)"] = "class ;"
map["pin (y)"] = "board ;"
map["pin (z)"] = "board2 ;"
}
答案 1 :(得分:0)
这可能对您有用(GNU sed):
sed '1{x;s/^/;,/;x};/^cell (a)/I,/^}/{/pin (q)/I{x;s/;/&q/;/;q\{2\},/{x;p;s/pin.*/class ;/;x};x};/pin (y)/I{x;s/,/&y/;/,y\{2\}$/{x;p;s/pin.*/board ;/;x};x}}' file
使用几个定界符(;
的计数器pin (q)
和,
的计数器pin (y)
)分隔保留空间。将处理限制为cell (a)
。每次遇到pin (q)
或pin (y)
时,请在保留空间中为其相应的计数器添加一个。如果计数器为2(可以是任何数字),则打印当前行,然后修改当前行以反映附加的字符串。
编辑: 由于原始问题已更改:
sed '/cell ([^)]*)/{h;x;s/^/;:,/;x};G;/cell (edit[ab])/{/pin (q)/I{x;s/;/&q/;/;q\{2\}:/{x;P;s/\S.*/"class";/;x};x};/pin (yz)/I{x;s/:/&y/;/:y\{2\},/{x;P;s/\S.*/board/;x};x}};P;d' file
答案 2 :(得分:0)
Perl解决方案。这可以用作Unix过滤器。因此,如果它在名为transform
的文件中,则应将其运行为:
$ transform < input.txt > output.txt
代码如下:
#!/usr/bin/perl
use strict;
use warnings;
my $in_cell_a;
my $brace_level = 0;
my ($pin_q, $pin_y);
while (<>) {
print;
if (/{/) {
$brace_level++;
}
if (/cell \(a\)/) {
$in_cell_a = $brace_level;
}
if (/(\s*)pin \(Q\)/) {
if ($pin_q) {
print "${1}class ;\n";
$pin_q = 0;
} else {
$pin_q = 1;
}
}
if (/(\s*)pin \(y\)/) {
if ($pin_y) {
print "${1}board ;\n";
$pin_y = 0;
} else {
$pin_y = 1;
}
}
if (/}/) {
if ($brace_level == $in_cell_a) {
$in_cell_a = 0;
}
$brace_level--;
}
}
更新:这是使用更多数据驱动方法的更新版本。要添加额外的转换,您只需将其添加到$fix
变量中即可。
#!/usr/bin/perl
use strict;
use warnings;
my $in_edit_block;
my $brace_level = 0;
my $fix = {
'pin (Q)' => "class ;\n",
'pin (y)' => "board ;\n",
};
my $flag;
my $fix_re = join '|', map { "\Q$_\E" } keys %$fix;
while (<>) {
print;
if (/{/) {
$brace_level++;
}
if (/\Qcell (a)/) {
$in_edit_block = $brace_level;
}
if ($in_edit_block) {
if (my ($pad, $match) = /(\s*)($fix_re)/) {
if ($flag->{$match}) {
print "${pad}$fixes->{$match}";
$flag->{$match} = 0;
} else {
$flag->{$match} = 1;
}
}
}
if (/}/) {
if ($brace_level == $in_edit_block) {
$in_edit_block = 0;
}
$brace_level--;
}
}
答案 3 :(得分:0)
如果单元格(a)的块数超过1个...
awk '
function addline(ind, value) {
if(++a[ind]==2) {
b=$0
sub(/[^[:blank:]].*/,"",b)
$0=$0 "\n" b value " ;"
}
}
/^cell/ {
split("",a)
f=0
if(/(a)/)
f=1
}
$0 ~ "pin [(]Q[)]" && f {
addline("Q", "class")
}
$0 ~ "pin [(]y[)]" && f {
addline("y", "board")
}
1' input.txt