vim script之牛刀小试

Vim、Emacs配置和使用
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

vim script之牛刀小试

#1

帖子 hjjdebug » 2009-04-22 9:04

vim script之牛刀小试
帮助文档中script 举例没有多少使用价值。
vim 插件又太过复杂。
我这里有一个问题,希望vim 高手能用script 加以解决。

问题:考试题目录编辑
录入的文件格式如下:

试题1 5分 第3页
试题2 3分 第5页
....
假如试题为100到题: 序号1 - 100
分数为1-10 分
页号为< 300 页
如果手工输入,虽然vim编辑力很强,但100项yank,paste,modify也不厌其烦。
这里我们先编辑一个文件叫input.txt, 内容:
分数:5 3 8 7 9 10 2...
页号: 3 5 9 11 13 15 18...
然后以input.txt 为素材,编辑一个vim script, 一执行,就把我们的目录插到了光标处。

单就目录编辑而言,c/c++, perl等有它们自己的方式可以处理,就是打开input.txt来读
打开目录文件来写。但这里要体现vim script 的魅力,它的可视编辑能力。
它的文件的读入,数据的处理,界面元素的控制等等。 vim script 是一种解释型语言,
但我现在很菜,不足以处理这些问题,所以请高手给出答案。先代表菜鸟们表示感谢!
:em01 :em01
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: vim script之牛刀小试

#2

帖子 hjjdebug » 2009-04-27 9:32

这么久没人回帖,是不是没说清楚啊!好,给个c++的例子,希望换一个vim script 例子
input.txt:
----------------------------
分数: 5 3 8 7 9 10 2
页号: 3 5 9 11 13 15 18
-----------------------------
运行后面的c++程序后执行结果。
----------------------------
试题1 分数5 页号3
试题2 分数3 页号5
试题3 分数8 页号9
试题4 分数7 页号11
试题5 分数9 页号13
试题6 分数10 页号15
试题7 分数2 页号18
请按任意键继续. . .
-------------------------------
附c++程序
#pragma warning(disable:4786)
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>
#include <sstream>
using namespace std;
int main()
{
fstream f("input.txt");
if(!f.is_open())
{
cout << "error open file"<<endl;
}
int no=1;
string s,s1,s2;
vector<string> ss;
while(getline(f,s))
{
// cout<<s<<endl;
ss.push_back(s);
}
cout.setf(ios::left);
for(int i=0; i<ss.size(); i+=2)
{
istringstream line1(ss);
istringstream line2(ss[i+1]);
line1>>s1,line2>>s2; // discard first element
while(line1>>s1 && line2>>s2)
{
cout <<"试题"<<setw(6)<<no++<<"分数"<<setw(6)<<s1<<"页号"<<setw(6)<<s2<<endl;
}

}

system("pause");
return 0;
}
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: vim script之牛刀小试

#3

帖子 eexpress » 2009-04-27 9:40

c++作这事情啊。来perl吧。估计bash也行。
● 鸣学
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

Re: vim script之牛刀小试

#4

帖子 xiooli » 2009-04-27 9:48

第几页是什么意思?vim里面不是一万米长的文件都是一页么?
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

Re: vim script之牛刀小试

#5

帖子 xiooli » 2009-04-27 11:14

要是只按照你输出的例子来的话一个awk脚本可以搞定:

代码: 全选

xiooli@ubuntu:~$ cat tmp.awk 
{
for(i=2;i<=NF;i++){
j=i-2
if($0~/^分数/)score[j]=$i
if($0~/^页号/)page[j]=$i
}
}
END{
for(i=0;i<NF-1;i++)print "试题"i+1,"分数"score[i],"页号"page[i]
}
xiooli@ubuntu:~$ cat input.txt 
分数: 5 3 8 7 9 10 2
页号: 3 5 9 11 13 15 18
xiooli@ubuntu:~$ awk -f tmp.awk input.txt 
试题1 分数5 页号3
试题2 分数3 页号5
试题3 分数8 页号9
试题4 分数7 页号11
试题5 分数9 页号13
试题6 分数10 页号15
试题7 分数2 页号18
xiooli@ubuntu:~$ 
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: vim script之牛刀小试

#6

帖子 hjjdebug » 2009-04-27 15:47

谢谢两位,但我这里不是要用bash,perl,sed,awk,c/c++,java.....
就这个很简单的功能,需要用vim script 来解决。 写好后命名为test.vim
test.vim 负责打开input.txt, 分析内容,并向屏幕插入内容。
我们用vim打开一个空文件, 执行:so test.vim
则相应结果插入到光标处。
试题1 分数5 页号3
试题2 分数3 页号5
试题3 分数8 页号9
试题4 分数7 页号11
试题5 分数9 页号13
试题6 分数10 页号15
试题7 分数2 页号18

此题目的是为了学习一下vim 编程技巧,,
毕竟可视编程还是有它的魅力所在,希望大侠不吝赐教!
头像
Strange
帖子: 1824
注册时间: 2006-05-19 9:54
来自: Shanghai

Re: vim script之牛刀小试

#7

帖子 Strange » 2009-04-27 16:55

要是编程就没有可视内容了...
这种小问题,手动录一个宏就解决了。
ニンニク入れますか?
x60 with gentoo
头像
xiooli
帖子: 6956
注册时间: 2007-11-19 21:51
来自: 成都
联系:

Re: vim script之牛刀小试

#8

帖子 xiooli » 2009-04-27 17:51

hjjdebug 写了:谢谢两位,但我这里不是要用bash,perl,sed,awk,c/c++,java.....
就这个很简单的功能,需要用vim script 来解决。 写好后命名为test.vim
test.vim 负责打开input.txt, 分析内容,并向屏幕插入内容。
我们用vim打开一个空文件, 执行:so test.vim
则相应结果插入到光标处。
试题1 分数5 页号3
试题2 分数3 页号5
试题3 分数8 页号9
试题4 分数7 页号11
试题5 分数9 页号13
试题6 分数10 页号15
试题7 分数2 页号18

此题目的是为了学习一下vim 编程技巧,,
毕竟可视编程还是有它的魅力所在,希望大侠不吝赐教!
哈哈,可以在vim下执行嘛 :em05

代码: 全选

:r !sh -c "awk -f ./tmp.awk input.txt"
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: vim script之牛刀小试

#9

帖子 hjjdebug » 2009-04-27 18:21

to: Strange:
录一个宏不太好解决,因为分数和页号总在变。这些变化在input.txt 中保留着。
这个题的目的就是要用vim script 打开一个文件,读取信息保存到变量中。 然后添加必要信息输出到屏幕上。
这是我想的一个题目,目的是体现一下vim script 的编程套路。
对于那些写vim 插件的人,这肯定是个小case., a piece of cake!


to: xioodi:
老兄还记着自己的awk, 就是有点跑题了。您使本帖的人群增加不少,欢迎! :em06
头像
Strange
帖子: 1824
注册时间: 2006-05-19 9:54
来自: Shanghai

Re: vim script之牛刀小试

#10

帖子 Strange » 2009-04-27 18:50

录一个宏不太好解决,因为分数和页号总在变。这些变化在input.txt 中保留着。
当然是可以解决的。虽然和你想做的事情有点不同。
我喜欢操作系>script,毕竟用了script,还不如用其他script language

我来操作的话
分数: 5 3 8 7 9 10 2
页号: 3 5 9 11 13 15 18
先操作这些

代码: 全选

:%s/ /\r/g
:let a = 1
ggj
然后把下面这些录成宏

代码: 全选

O
<esc>
:call setline(line("."), a)
:let a = a + 1
I
试题
<esc>
j
I
分数
<esc>
/页号<enter>
j
dd
``
p
I
页号
<esc>
kk
JJ
j
最后随便来个9999@a就解决问题了
分数:
试题1 分数5 页号3
试题2 分数3 页号5
试题3 分数8 页号9
试题4 分数7 页号11
试题5 分数9 页号13
试题6 分数10 页号15
试题7 分数2 页号18
试题8
分数页号:
看着多出来的东西不爽,录一个宏删掉就可以了
这样才是可视操作嘛 :em02
ニンニク入れますか?
x60 with gentoo
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: vim script之牛刀小试

#11

帖子 hjjdebug » 2009-04-28 14:22

Strange 写了: O
<esc>
:call setline(line("."), a)
:let a = a + 1
I
试题
<esc>
j
I
分数
<esc>
/页号<enter>
j
dd
``
p
I
页号
<esc>
kk
JJ
j
谢谢strange!
我明白你的意思了, 你是直接读取input.txt, 进行可视编辑。
上面的script 我想你不能够直接记录产生吧,是先编辑script,再copy 到寄存器a中吧。
宏适合记录简单的击键操作。
上面的script 如果不是记录产生,而是手工编辑,是不是很容易出错呀?

目前讨论的是直接编辑input.txt,产生需要的结果输出。
头像
Strange
帖子: 1824
注册时间: 2006-05-19 9:54
来自: Shanghai

Re: vim script之牛刀小试

#12

帖子 Strange » 2009-04-28 15:10

我明白你的意思了, 你是直接读取input.txt, 进行可视编辑。
上面的script 我想你不能够直接记录产生吧,是先编辑script,再copy 到寄存器a中吧。
宏适合记录简单的击键操作。
当然是直接记录的,按照我的顺序按键你就明白了,需要回车的地方我都写出来了...
宏功能很强的,不然我这些东西怎么来的...
ニンニク入れますか?
x60 with gentoo
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: vim script之牛刀小试

#13

帖子 hjjdebug » 2009-04-28 18:47

Strange 写了: 当然是直接记录的,按照我的顺序按键你就明白了,需要回车的地方我都写出来了...
宏功能很强的,不然我这些东西怎么来的...
实验过了! :em11
原来我只会用宏记录操作,没有记录过:let :call setline 等。
:let :call 有点script 味道了。该例子足以显示宏的强大了。
实际上我是想通过该例子学习更多的script 知识,被你轻易的用宏解决了,也好! :em09

script 是vim的幕后英雄,只有它能与vim无缝结合,回头我再找例子跟你学学插件编写,先谢谢!
知道了在宏中还可以穿插语句,很高兴,宏的功能更强大了! :em11
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: vim script之牛刀小试

#14

帖子 hjjdebug » 2009-04-29 8:31

点评:
该宏只用了一个变量 a, 保存试题号。用line函数获取行号,用setline函数添加内容。 其它是常规操作命令。vim script 牛刀刚一出鞘,小鸡就已经没戏了。 回头找个牛,看看牛刀怎么用。 :em04
starwing
帖子: 100
注册时间: 2008-09-19 1:03

Re: vim script之牛刀小试

#15

帖子 starwing » 2009-05-01 11:30

代码: 全选

try
    let list = readfile('input.txt')
catch
    let list = ['分数:1 2 3 4', '页号:5 4 3 2']
endtry
let scores = split(matchstr(list[0], '分数:\zs.*'))
let pages = split(matchstr(list[1], '页号:\zs.*'))
let res = []

let i = 1
for sc in scores
    let res += ['试题'.i.' '.sc.'分 第'.pages[i-1].'页']
    let i += 1
endfor

call append(line('$'), res)
finish

LZ尝试一下?复制到vim,然后保存到a.vim,最后转到input.txt所在文件夹再:so%,列表会出现在finish下面……

附带示例,如果读取文件失败,会显示处理示例的结果
回复