Chinaunix首页 | 论坛 | 博客
  • 博客访问: 125160
  • 博文数量: 19
  • 博客积分: 810
  • 博客等级: 准尉
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-14 23:34
文章分类

全部博文(19)

文章存档

2010年(2)

2009年(12)

2008年(5)

我的朋友

分类: LINUX

2009-07-11 14:38:55

      前几天在实验室一个师姐在写Verilog代码时问了我一个问题,就是她需要定义一系列变量output rca_out_data0~rca_out_data15,现在她已经写好output rca_out_data0,然后复制了15行,她问我怎么把data后面的0一次替换成1~15,我不假思索的说,用脚本呗(我以前coding碰到这种情况都是用perl -ne来做的)。她说不想用脚本,问能不能就用vim就实现,这我倒是没尝试过。这两天腰受伤了,闲在宿舍休息,于是为了解决这个问题,去网上搜了不少资料,经过整理,总结下述4条对于自己来说比较实用的替换技巧,其中第2条、第3条和第4条都可以完美的解决师姐的问题。过两天去实验室,又可以show一下这么cool的操作,哈哈~~~



1.替换变量

在正规表达式中使用 \( 和 \) 符号括起正规表达式,即可在后面使用\1、\2等变量来访问 \( 和 \) 中的内容。

example:
·将 data1 data2 修改为 data2 data1
-----------------------------------
:s/\(\w\+\)\s\+\(\w\+\)/\2\t\1
-----------------------------------
·将 Doe, John 修改为 John Doe
-----------------------------------
:%s/\(\w\+\), \(\w\+\)/\2 \1/    
-----------------------------------


2.利用函数式替换

用法:
---------------------------
:s/替换字符串/\=函数式
---------------------------
说明:
·函数式可以有多个,返回值可以用字符串连接符.连接起来,如line(".")返回匹配行号(:help line()  ),submatch(n)可以引用\1、\2的内容,其中submatch(0)引用匹配的整个内容;
·函数式也可以是字符串常量,用双引号引起来。函数式也可以是任意表达式,需要用小括号引起来,如(3+2*6);
·函数式还可以是寄存器中的内容,通过"@寄存器名"访问,如@a(不需要加引号,但是还是需要用.来连接);

example:
·要将下列8行的data0依次变成data0~7(前面的数字是行号)
double data0;
double data0;
double data0;
double data0;
double data0;
double data0;
double data0;
double data0;
如果安装有perl的话,我以前一般都是借助perl来完成这件事情:
---------------------------------------------------------------------------
:r !perl -n -le "if(s/^(double\s+data)\d;/$1$k;/){ $k++; print $_; }" %:p
---------------------------------------------------------------------------
其中%:p表示包含完整路径的文件名

现在只用vim我们就可以完成这样的事情:
首先将光标移到125行(line(".")返回当前匹配行的行号,line("'a")返回mark a的行号):
---------------------------------------------------------------------------
ma
:%s/^\(double\s\+data\)\d\(;\)/\=submatch(1).(line(".")-line("'a")+1).submatch(2)/g
---------------------------------------------------------------------------
再或者
首先将光标移到125行(line("'<")返回所选区域第一行的行号)
---------------------------------------------------------------------------
V7j
:%s/^\(double\s\+data\)\d\(;\)/\=submatch(1).(line(".")-line("'<")+1).submatch(2)/g
---------------------------------------------------------------------------


3.匹配的开始与结束

\zs\ze可以用于替换操作中指明替换的开始与结束,如上例中可以以更短的操作来实现:
---------------------------------------------------------------------------
ma
:%s#^double\s\+data\zs\d\ze#\=(line(".")-line("'a")+1)#g
---------------------------------------------------------------------------

另外,还可以使用vim表达式来实现上述功能:
---------------------------------------------------------------------------
:let n=0 | g/^double\s\+data\zs\d/s//\=n/ | let n+=1
---------------------------------------------------------------------------
其中 ·|      用来分割不用的命令;
    ·     在匹配后面模式的行中执行指定的ex命令
    ·\zs    指明匹配由此开始
    ·s//\=n 对匹配模式进行替换,匹配模式为空,表示以上一次匹配成功的模式,
             并且指明替换是一个表达式;


4. 高级递增替换

把下面几句放到 _vimrc
-------------------------------
let g:I=0
function! INC(increment)
  let g:I =g:I + a:increment
  return g:I
endfunction
------------------------------
·对于上述问题,可以这样解决:
-----------------------------------------------------
:let I=-1 | %s/^ double\s\+data\zs\d\ze/\=INC(1)/
-----------------------------------------------------
·还可以生成数字序列,如生成1~100间隔为5的数字序列:
--------------------------------------
:let I=0 | ‘a,’b s/^/\=INC(5)/
--------------------------------------

更多高级递增可以参见:

·increment.vim : yet another script for incrementing numbers.

    

·Generating a column of increasing numbers

    

·Step increment and replace

    



5.进行四舍五入的替换操作(该部分转载)

298.896
448.344
597.792
149.448
224.172
298.896
448.344
149.448
224.172
以上的数据来自真实的需求, 目前需要把他们按四舍五入的原则取整.
vim7中引入了一种叫dictionary的数据类型, 即哈希. 利用他能对一些不同的源字串提供不同的替换:
-----------------------------------------------------------
:let a={0:0, 1:0, 2:0, 3:0, 4:0, 5:1, 6:1, 7:1, 8:1, 9:1}
-----------------------------------------------------------
一目了然, 0-4则取0, 舍, 5-9则取1, 进位.

-----------------------------------------------------------
:%s#^\(\d\+\)\.\(\d\)\d*#\=(submatch(1)+a[submatch(2)])#g
-----------------------------------------------------------
为了验证是否正确, 将上面的式子简单修改, 能输出下面的结果, 方便对比校验:
----------------------------------------------------------------------
:%s#^\(\d\+\)\.\(\d\)\d*#\=(submatch(0).'==>'.(submatch(1) + a[submatch(2)]))#g
----------------------------------------------------------------------
298.896==>299
448.344==>448
597.792==>598
149.448==>149
224.172==>224
298.896==>299
448.344==>448
149.448==>149
224.172==>224



结束

      越来越感叹VIM是个强大的软件,以前很多文本操作都需要用Perl脚本来完成,现在发现其实很多工作VIM完全可以胜任的,只是需要学习的东西太多了。
阅读(2031) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~