分页: 1 / 2
vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-15 21:27
由 cao627
比如文件1内容:
1
a1
其他
若干内容
2
a2
其他
若干内容
3
a3
其他
若干内容
比如文件2内容:
1
b1
其他
若干内容
2
b2
其他
若干内容
3
b3
其他
若干内容
如何实现将文件1的a1,a2,a3,......分别用文件2的b1,b2,b3,....替换。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-15 22:01
由 lilydjwg
录制宏,或者使用脚本语言。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-15 23:27
由 aerofox
可以使用 paste 命令把这两个文件合并成一个文件,再 sed 或者 vim 的 :s 命令去掉多余的内容。
例如:
代码: 全选
paste 文件1 文件2 | sed '1~4s/\t.*//;2~4s/.*\t//;3~4s/\t.*//;4~4s/\t.*//' > 新文件
这里假定两个文件中都不含制表符。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 15:57
由 Fermat618
用程序来做吧,先用个适合的数据结构把表示一下你的数据,后面就好弄了。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 17:14
由 cao627
aerofox 写了:可以使用 paste 命令把这两个文件合并成一个文件,再 sed 或者 vim 的 :s 命令去掉多余的内容。
例如:
代码: 全选
paste 文件1 文件2 | sed '1~4s/\t.*//;2~4s/.*\t//;3~4s/\t.*//;4~4s/\t.*//' > 新文件
这里假定两个文件中都不含制表符。
谢谢,研究了一下这个命令
paste 文件1 文件2 是依次将文件1的每一行后加一制表符然后贴上文件2对应的行上的内容
所以在sed命令中第一行 第三行 第四行 执行s /\t.*// 删除制表符后的内容,第二行执行s/.*\t//删除字表符前的内容,
得到的效果就是:
用文件1的第一行做为新文件的第一行,文件2的第二行做为新文件的第二行,文件1的3,4行作为新文件的3,4行。
最巧妙的应该是1~4,2~4,3~4,4~4,这一组东东的使用。
它们功能照得到效果来看,应该是:
将全文的所有行以4行为一个循环单位,依次执行它们后面的s操作。
最后
除了 两个文件中都不含制表符 的要求外
还要满足 两个文件中的 “其他若干内容“所占的行数必须是固定且相等的。否者1~N这样的功能就不能应用了。
3楼!看到的话再问问:
如果:两个文件中的 “其他若干内容“所占的行数不是固定,且(行数)也不是对应相等的。
有办法吗?
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 17:32
由 eexpress
特征是1,2,3这些数字行后面的一行,要替换?
我担心你只是说了一个特例,而不是规律。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 17:54
由 cao627
eexpress 写了:特征是1,2,3这些数字行后面的一行,要替换?
我担心你只是说了一个特例,而不是规律。
文件一 1,2,3,........下面的一行 替换为文件二 1 ,2,3,....下面的一行
1,2,3,.....单独占一行 在文件一和文件二中都是唯一的,而且也是依次递增的,即3这一行之后,出现的一个数独占一行的话,一定是4
这也应该算个规律吧。
所谓规律,无非能从局部推出全部
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 18:04
由 eexpress
如果是这样的规律。脚本可以搞定。vim难。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 19:00
由 aerofox
代码: 全选
paste file1 file2 | sed '/^[[:digit:]]\+\t[[:digit:]]\+$/{s/\t.*//;N;s/\n.*\t/\n/}; s/\t.*//'
应该可以了吧?先不解释了,我看楼主应该自己能分析出来。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 19:23
由 aerofox
刚才没注意行数不是对应相等,这样的话,上面的命令不行,得用更复杂的脚本编程,python 比较方便。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 22:38
由 rykka
能实现,但是最好还是写成函数
代码: 全选
function! s:replaceby(file,repeat,num)
let b=readfile(a:file)
for i in range(line('$'))
if fmod(i,str2nr(a:repeat)) == a:num-1
let line = b[i]
" write line to current file
exe (i+1)."put ='".line."'"
exe (i+1)."del"
endif
endfor
endfunction
command! -nargs=* ReplaceBy call <SID>replaceby(<f-args>)
用法:
如果要用文件b中每4行的第2行...替换文件a中对应行数
在文件a中使用命令
如果不是重复相同行数的话,
则用
代码: 全选
if getline(i) =~ '^\d\+$'
来判断是否替换。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 22:42
由 cao627
aerofox 写了:代码: 全选
paste file1 file2 | sed '/^[[:digit:]]\+\t[[:digit:]]\+$/{s/\t.*//;N;s/\n.*\t/\n/}; s/\t.*//'
应该可以了吧?先不解释了,我看楼主应该自己能分析出来。
3楼你好 看到话帮忙看看
这条sed命令似乎可以最后一个分号做分界作这样理解:
分号前的部分做匹配和替换
然后再执行分号后的替换
但我执行
代码: 全选
paste a1 b1 | sed '/^[[:digit:]]\+\t[[:digit:]]\+$/{n;s/.*\t//};s/\t.*//'
发现所有数字行没有被;s/\t.*//'执行到
我的理解是/^[[:digit:]]\+\t[[:digit:]]\+$/匹配到数字行,接着根据前面得到的行做一个操作{n;s/.*\t//}
这个操作分两步 n 移到下行 接着做替换s/.*\t// 由于这两步是当作一个操作所以用了{}
然后;后面是新的操作 s/\t.*// 我的理解是这个操作是对分号前操作的到的全文结果重新行执行s/\t.*//操作,即相当于
代码: 全选
paste a1 b1 | sed '/^[[:digit:]]\+\t[[:digit:]]\+$/{n;s/.*\t//}' | sed 's/\t.*//'
但从执行结果来看这个理解好行不太对.这里能解释下吗
另外N 的解释网上看的不是很明白。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 22:50
由 aerofox
经过试验,基本上用 vim 做到了,过程比较复杂,看看是否符合楼主的要求:
准备工作,不管用什么工具,从文件2中提取出要送给文件1的那些数据,并在最后加上一行随便什么数据(有一行就行),放到一个新文件中。用 sed 实现这一步的例子为:
代码: 全选
sed -n '/^[[:digit:]]\+$/{n;p};$p' file2 > tmpfile
用 vim 同时打开两个文件1 和 刚才生成的临时文件,在垂直分隔的两个窗口(只vim内部split出来的窗口)中编辑,文件1 位于左侧。
代码: 全选
vim -O file1 tmpfile
然后确保右侧编辑缓冲区中光标位于第一行,在激活左侧 file1 的情况下,执行下面这条 vim 命令
代码: 全选
:g/^\d\+$/+1 normal dd^Wlyyj^WhP
其中 ^W 代表 Ctrl-W,要用 Ctrl-V 加 Ctrl-W 输入。
解释:
代码: 全选
g/^\d\+$/+1
全局查找只包含数字的行,每次找到后,将其下一行作为当前行,执行后面的命令
normal
执行后面的 normal 模式操作
dd
删除当前行
^Wl
换到右侧窗口
yyj
拷贝一行,光标下移,为下一次拷贝做准备。如果临时文件最后没有多余的一行,则最后一次j命令会失败。
^WhP
换到左侧窗口后执行粘贴操作
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 23:23
由 cao627
谢谢,思路看懂了,琢磨一下。
Re: vim能否实现将一个文件的多处内容替换另一个文件的相应内容?
发表于 : 2012-03-16 23:49
由 aerofox
再来一个 sed 的版本,更简洁些:
代码: 全选
sed -f <( sed -n '/^[[:digit:]]\+/{s:.*:/^&$/{n;s/.*/:;N;s/\n//;s:$:/}:;p}' file2 ) file1
思路:
先根据 file2 的内容生成一个 sed 脚本,再用这个脚本来修改 file1。从 file2 生成的 sed 脚本是这个样子:
代码: 全选
/^1$/{n;s/.*/b1/}
/^2$/{n;s/.*/b2/}
/^3$/{n;s/.*/b3/}
如果 b1、b2、b3 等地方会有 &、\L 等对 sed 脚本 s 命令来说有特别含义的内容时,这种做法会出问题。