使用Vi / Vim将每行中的字符串替换为搜索结果

时间:2014-11-08 14:33:29

标签: unix vim vi

我有一个显示ls

输出的文件

e.g。

/home/john/A_2014.jpg
/home/john/B_2014.jpg
/home/john/C_2014.jpg
/home/john/D_2014.jpg

现在我想使用此输出为mysql编写插入脚本。 我实现了在每行的开头和结尾输入必要的代码,所以文件实际上是这样的:

INSERT INTO myimages (name,picture) values ('#name',LOAD_FILE('/home/john/A_2014.jpg'));
INSERT INTO myimages (name,picture) values ('#name',LOAD_FILE('/home/john/B_2014.jpg'));
INSERT INTO myimages (name,picture) values ('#name',LOAD_FILE('/home/john/C_2014.jpg'));
INSERT INTO myimages (name,picture) values ('#name',LOAD_FILE('/home/john/D_2014.jpg'));

有没有办法用#name之前的字符串替换_2014.jpg,以便最终输出看起来像

INSERT INTO myimages (name,picture) values ('A',LOAD_FILE('/home/john/A_2014.jpg'));
INSERT INTO myimages (name,picture) values ('B',LOAD_FILE('/home/john/B_2014.jpg'));
INSERT INTO myimages (name,picture) values ('C',LOAD_FILE('/home/john/C_2014.jpg'));
INSERT INTO myimages (name,picture) values ('D',LOAD_FILE('/home/john/D_2014.jpg'));

不幸的是,有很多行可以手工完成。谢谢你的帮助。

3 个答案:

答案 0 :(得分:1)

之前

/home/john/A_2014.jpg
/home/john/B_2014.jpg
/home/john/C_2014.jpg
/home/john/D_2014.jpg

命令

:%s@\v.*/([^/]+)_2014.*@...\1...&...@

...A.../home/john/A_2014.jpg...
...B.../home/john/B_2014.jpg...
...C.../home/john/C_2014.jpg...
...D.../home/john/D_2014.jpg...

如你所见:

  • 使用@作为分隔符
  • 使用\v使正则表达式非常神奇
  • 使用(...)捕获一个组,然后将其引用为\1
  • 使用&引用整个匹配的行

答案 1 :(得分:1)

基于kev的答案,该答案显示了如何使用反向引用,如果要替换“名称”文本,还需要限制将被替换的文本。

整个文件的示例(使用您的:

:%s@\v.*'\zs#name\ze'.*/([^/]+)_2014.*@\1@

\zs设置匹配的起始位置,\ze设置结束位置。这使您可以限制替换的文本。正如kev所提到的,替换文本中的\1指的是搜索模式中(...)组中捕获的文本。搜索模式本身匹配:

.*    - any text
'     - an opening literal single quote
#name - the literal text, #name
'     - the closing quote
.*    - any text again
/     - the final '/' in the line
(     - start capturing a backreference
[^/]+ - at least one non-slash character (matches A, B, etc.)
)     - end backreference capture
_2014 - matches this text literally
.*    - any other text

替换\1会将所有匹配项替换为捕获的反向引用,但请记住,我们使用\zs\ze将匹配限制为#name字符串。

答案 2 :(得分:0)

“宏+替代”解决方案......

  1. 将光标放在第一行进行编辑,然后将宏记录在寄存器q中:

    qq
    0/_2<CR>
    yh
    :s/#name/<C-r>"<CR>
    q
    
  2. 播放宏:

    :+,$norm! @q<CR>