./a.temp.txt ./a.temp.txt
./a/b.temp.txt ./a/b.temp.txt
./a/b/c.temp.txt ./a/b/c.temp.txt
我想删除每行上的
temp.
,但是仅第二次出现,因此该文件应如下所示:./a.temp.txt ./a.txt
./a/b.temp.txt ./a/b.txt
./a/b/c.temp.txt ./a/b/c.txt
我应该怎么做?
#1 楼
通常,您可以使用\zs
和\{N}
匹配某事的第N次出现。在:help \zs
处有一个示例。您的情况下的命令是:
:%s/\(.\{-}\zstemp\.\)\{2}//
评论
使用verymagic标记,可以减少正则表达式:%s / \ v(。{-} \ zstemp。){2} //
– nobe4
16年7月8日在6:40
#2 楼
使用sed
可以更轻松地完成此操作:sed 's/\.temp\././2'
使用Vim,您需要非贪婪匹配,并且很难将方法扩展为替换第3,第4个等发生
temp
。但是只要您坚持就可以做到::%s/\.temp\..\{-}\.\zstemp\.//
评论
感谢您提供sed解决方案,您认为可以在每行中应用它吗?
– nobe4
16年7月7日在11:28
@ nobe4不知道那是什么意思。 sed依次将脚本应用于输入的每一行。
–佐藤桂
16年7月7日在11:30
是的,但是您可以将行传递到外部程序中并返回结果。
– nobe4
16年7月7日在11:32
你是说Vim吗?当然,您可以通过管道传输sed,就像您可以通过管道将其传输到任何其他程序一样。 F.i .::%!sed's / \。temp \ ././ 2'。以UNIX友好的sed格式,它从stdin读取输入并将结果写入stdout。
–佐藤桂
16年7月7日在11:35
#3 楼
您也可以回过头来执行此操作。:%s/\(temp\..*\)\@<=temp\.//
如果要删除第一次出现的所有事件,可以在末尾附加
g
标志。\(\)\@<=
将搜索\(
和\)
之间的任何模式,但不会将找到的文本添加到匹配项中。 有关更多信息,请参见
:h \@<=
。#4 楼
您可以使用已经建议的@Meshpi宏。但是,这是完成同一件事的另一种方法。02/temp^Mdwx+
0-转到行的开头
2 / temp-搜索temp并转到第二个出现的位置
^ M-只需按Enter键
dw-删除单词(temp)
x-删除'。'
+-转到下一行的开头
然后,您可以重复直到最后。并且,将有更多的方法可以做到这一点。
#5 楼
此解决方案与TessellatingHeckler的解决方案类似,但更易于适应必须删除的任何模式。br />
:g/temp\./
对于与“温度”匹配的每一行。normal
在正常模式下执行以下操作2n
找到模式的第二次出现gn
选择它d
并将其删除。这将适用于任何情况模式被赋予
:g
。normal
可以缩写为norm
。gnd
等同于dgn
。编辑:实际上
2ngnd
等同于d2gn
。请参见Vim Tips Wiki提供了有关全局命令的更多示例。
#6 楼
在Vim中,可以定义要与:help \%c
进行匹配的之前/之后/之后的列::%s/\%>17c\.temp/g
这将消除在列之后找到的每个
.temp
当前缓冲区中每行的17。注1:您的示例不需要
/g
。注2:我非常方便地使用了该功能经常与qmv一起使用。推荐!
评论
整洁,我当时正在考虑制作一个插件,但这很好!
– nobe4
16年7月7日在12:35
Vim已经做了很多事情……
– romainl
16年7月7日在12:37
可以,但是我不知道这个工具。一点脚本总是很有趣!
– nobe4
16年7月7日在12:38
@ nobe4如果您关心这种事情,请参见moreutils软件包中的vidir和vipe。
–佐藤桂
16年7月7日在13:17
#7 楼
这实际上很简单。要匹配第二个温度,允许在其后加上“ temp”,然后再寻找温度。%s/.*temp.*\zstemp\.
\zs
的意思是“从此处开始选择”,因此比赛的第一部分(第二温度之前的所有内容)不会被删除。实际上,这是我刚刚学到的极其有用的功能!没有它,则正则表达式必须如下所示::%s/\(.*temp.*\)temp\./
评论
如果一行上有两个以上的温度,则您的配方会删除最后一个而不是第二个。责怪贪婪。 :)
–lcd047
16年7月7日在20:13
是的,这很贪婪,因此它删除了最后一个。但是,OP表示我的情况是将旧文件名与新文件名匹配,因此每行仅出现2次。而且只有第二个应该改变。
–詹姆斯
16年7月7日在20:15
#8 楼
代替正则表达式,我将执行以下命令:跳转到行尾
向后搜索
temp
删除5个字符
并在每一行上运行它:
:g//normal $?temp^[5x
NB。
^[
是特殊的,表示按Escape键;您可以使用以下命令键入它:Ctrl-q <Esc>
但是正则表达式选项(我认为还没有建议)是匹配
temp.
,后跟除.
之外的其他任何内容,并固定到该行。:%s/temp\.\([^.]\+\)$//
将与行尾的
temp.txt
匹配,并仅用txt
位替换。#9 楼
我将用光标从左上角开始写一个宏。qq4f.dfpq
然后我将使用
V
选择其余的行,并使用:'<,'>norm!@q
在这些行上运行宏仅当文本格式相对于第二个温度之前的点数保持相同时,此方法才有效。
评论
若要使您的宏更健壮,应使用搜索和n而不是4f。因为如果文件名中包含更多的点,您的宏可能会失败或删除不应删除的内容。
–statox♦
16年7月7日在11:28
#10 楼
没有什么可以阻止您使用两个正则表达式而不是一个,即更改第一个正则表达式然后交换列:可读性强。
#11 楼
我的尝试:%norm 4ftdwx
:%norm ......... execute in normal mode over the whole file
4ft ............ the 4th t matches the start of the second temp
dw ............. deletes the current word
x .............. deletes the dot
评论
是否可能在任何一行上出现第三或第四次出现?这些必须保持完好吗?我的情况是将旧文件名与新文件名匹配,因此每行仅出现2次。而且只有第二个应该更改。