在日常的工作中,经常会遇到处理log或者文本的一些工作。但一时又想不到如果解决,提笔忘脚本。由此,我总结一些小的方法,给自己梳理一下思路,同时帮助别人。
按照文本处理的复杂程度,我们来决定用什么方法处理:
- 如果文本本身size不大,只是关键字的替换或者列操作等,那么就用编辑器处理了,比如vim或者Emacs。
- 不想用编辑器打开文本,并且需要集成到其他脚本或者Makefile中,操作多是单行的,便于以后重复使用,推荐sed或者awk。
- 需要处理比较复杂,或者要生成一些代码,推荐使用Perl。
先说第一种情况,比如下面的代码。想要在下面的前四行代码,每行后面增加一些注释,比如"they are inputs"。
input a;
input b;
input c;
input d;
output e;
先以vim为例,按ESC进入命令模式,在第一行按下“ma”,第四行按下“mb”,标记了我们想要操作的区域。然后按“:”,输入命令“'a,'bs/;$/; \/\/ they are inputs”;
“'a”和“'b”就是我们刚才标记的起点和终点,格式“s/xx/yy/”表示将“xx”替换成“yy”。注意这里,如果“yy”中包含“/”,需要使用反斜线进行转义。
<img src="../../images/textprocessing1vim.gif" class="img-thumbnail" width="60%" >
如果是Emacs,在第一行,组合键C-S-SPACE标记区域的开始,光标来到在第五行的开头,可以看到我们选中了前四行,然后M-%,进行替换,最后的!表示全部替换。
<img src="../../images/textprocessing1emacs.gif" class="img-thumbnail" width="60%" >
再说第二种情况,文本比较大,不想打开,想把里面包含“delete me please!”的行都删掉。可以使用sed。
sed -e '/delete me please!/d' text.txt -i
-e表示执行的命令,其中“/xx/d”表示去匹配xx然后删除,-i表示处理结果写会到原文件。
最后是第三种情况,比如有一个文本文件如下:
module a;
input i_a;
input i_a_not_this;
output o_a;
endmodule // a
module b;
input i_b;
input i_b_not_this;
output o_b;
endmodule // b
我们想要把module b里的第一个input信号的名字换成module a里的第一个input信号的名字,这样比较适合Perl来做。
my $in_a_module = 0;
my $in_b_module = 0;
my $input_a;
my $end = 0;
while (my $line = <>) {
if ($in_b_module == 1) {
if ((defined ($input_a)) && ($end == 0)) {
$line =~s/input(\s+)\w+/input$1$input_a/;
$line .= " // The line above is changed.\n";
$end = 1;
}
if ($line =~/endmodule/) {
$in_b_module = 0;
}
} else {
if ($in_a_module == 1) {
if ($line =~/input\s+(\w+)/) {
if (! defined $input_a) {
$input_a = $1;
} else {
}
}
if ($line =~/endmodule/) {
$in_a_module = 0;
}
} else {
if ($line =~/module a/) {
$in_a_module = 1;
}
if ($line =~/module b/) {
$in_b_module = 1;
}
}
}
print $line;
}
运行的结果是:
module a;
input i_a;
input i_a_not_this;
output o_a;
endmodule // a
module b;
input i_a;
input i_b_not_this;
output o_b;
endmodule // b