分页: 1 / 2
vim script之牛刀小试
发表于 : 2009-04-22 9:04
由 hjjdebug
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 是一种解释型语言,
但我现在很菜,不足以处理这些问题,所以请高手给出答案。先代表菜鸟们表示感谢!

Re: vim script之牛刀小试
发表于 : 2009-04-27 9:32
由 hjjdebug
这么久没人回帖,是不是没说清楚啊!好,给个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;
}
Re: vim script之牛刀小试
发表于 : 2009-04-27 9:40
由 eexpress
c++作这事情啊。来perl吧。估计bash也行。
Re: vim script之牛刀小试
发表于 : 2009-04-27 9:48
由 xiooli
第几页是什么意思?vim里面不是一万米长的文件都是一页么?
Re: vim script之牛刀小试
发表于 : 2009-04-27 11:14
由 xiooli
要是只按照你输出的例子来的话一个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:~$
Re: vim script之牛刀小试
发表于 : 2009-04-27 15:47
由 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 编程技巧,,
毕竟可视编程还是有它的魅力所在,希望大侠不吝赐教!
Re: vim script之牛刀小试
发表于 : 2009-04-27 16:55
由 Strange
要是编程就没有可视内容了...
这种小问题,手动录一个宏就解决了。
Re: vim script之牛刀小试
发表于 : 2009-04-27 17:51
由 xiooli
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下执行嘛
代码: 全选
:r !sh -c "awk -f ./tmp.awk input.txt"
Re: vim script之牛刀小试
发表于 : 2009-04-27 18:21
由 hjjdebug
to: Strange:
录一个宏不太好解决,因为分数和页号总在变。这些变化在input.txt 中保留着。
这个题的目的就是要用vim script 打开一个文件,读取信息保存到变量中。 然后添加必要信息输出到屏幕上。
这是我想的一个题目,目的是体现一下vim script 的编程套路。
对于那些写vim 插件的人,这肯定是个小case., a piece of cake!
to: xioodi:
老兄还记着自己的awk, 就是有点跑题了。您使本帖的人群增加不少,欢迎!

Re: vim script之牛刀小试
发表于 : 2009-04-27 18:50
由 Strange
录一个宏不太好解决,因为分数和页号总在变。这些变化在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
分数页号:
看着多出来的东西不爽,录一个宏删掉就可以了
这样才是可视操作嘛

Re: vim script之牛刀小试
发表于 : 2009-04-28 14:22
由 hjjdebug
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,产生需要的结果输出。
Re: vim script之牛刀小试
发表于 : 2009-04-28 15:10
由 Strange
我明白你的意思了, 你是直接读取input.txt, 进行可视编辑。
上面的script 我想你不能够直接记录产生吧,是先编辑script,再copy 到寄存器a中吧。
宏适合记录简单的击键操作。
当然是直接记录的,按照我的顺序按键你就明白了,需要回车的地方我都写出来了...
宏功能很强的,不然我这些东西怎么来的...
Re: vim script之牛刀小试
发表于 : 2009-04-28 18:47
由 hjjdebug
Strange 写了:
当然是直接记录的,按照我的顺序按键你就明白了,需要回车的地方我都写出来了...
宏功能很强的,不然我这些东西怎么来的...
实验过了!
原来我只会用宏记录操作,没有记录过:let :call setline 等。
:let :call 有点script 味道了。该例子足以显示宏的强大了。
实际上我是想通过该例子学习更多的script 知识,被你轻易的用宏解决了,也好!
script 是vim的幕后英雄,只有它能与vim无缝结合,回头我再找例子跟你学学插件编写,先谢谢!
知道了在宏中还可以穿插语句,很高兴,宏的功能更强大了!

Re: vim script之牛刀小试
发表于 : 2009-04-29 8:31
由 hjjdebug
点评:
该宏只用了一个变量 a, 保存试题号。用line函数获取行号,用setline函数添加内容。 其它是常规操作命令。vim script 牛刀刚一出鞘,小鸡就已经没戏了。 回头找个牛,看看牛刀怎么用。

Re: vim script之牛刀小试
发表于 : 2009-05-01 11:30
由 starwing
代码: 全选
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下面……
附带示例,如果读取文件失败,会显示处理示例的结果