正则表达式, 匹配字符 但不匹配第一个字符

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

正则表达式, 匹配字符 但不匹配第一个字符

#1

帖子 hjjdebug » 2014-10-28 13:02

我有如下文件:
[ ~]$ cat 1.txt
abc_123 ab_12
abc_1234 abcd_23
abc_12 a_456


现在想把第二个_ 改为#字符, 应该怎样使用正则一次搞定。

改完后效果应为:
[~]$ cat 1.txt
abc_123 ab#12
abc_1234 abcd#23
abc_12 a#456

thanks!
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#2

帖子 cao627 » 2014-10-28 14:43

代码: 全选

sed -i  's/_/#/2' 1.txt
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#3

帖子 hjjdebug » 2014-10-29 9:14

to: cao627
这确实是sed 命令的一个技巧,把这个技巧扩展一下,
请问一下如果是把最尾部,就是倒数第一个_改为#该怎样写. sed -i 's/_/#/-1' 1.txt 的写法是不行的。 thanks!



另外,我的本意是想用vim 的%s 来完成修改,但是找不到一种合适的写法。希望是用一种通用的正则技巧, 不仅仅是特定于莫个命令的技巧。
头像
astolia
论坛版主
帖子: 6454
注册时间: 2008-09-18 13:11

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#4

帖子 astolia » 2014-10-29 9:45

代码: 全选

sed 's/\(.*\)_\([^_]*\)/\1#\2/' file
vim

代码: 全选

:%s/\(.*\)_\([^_]*\)/\1#\2/e
vim中把第N+1个pattern替换成string的通用写法

代码: 全选

:s/\%(\(pattern\).\{-}\)\{N}\zs\1/string/e
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#5

帖子 hjjdebug » 2014-10-29 16:16

to astolia

:%s/\(.*\)_\([^_]*\)/\1#\2/e 意思是成组匹配,最后把匹配到的两组组装在一起。

:s/\%(\(pattern\).\{-}\)\{N}\zs\1/string/e 替换第N+1 pattern 语法复杂,能否解释一下呢?
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#6

帖子 cao627 » 2014-10-29 18:47

就是倒数第一个_改为#该怎样写

代码: 全选

 sed 's/\(.*\)_/\1#/'
这样写就可以了,正则\(.*\)_会贪婪匹配到最后一个_
头像
astolia
论坛版主
帖子: 6454
注册时间: 2008-09-18 13:11

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#7

帖子 astolia » 2014-10-29 20:38

hjjdebug 写了::s/\%(\(pattern\).\{-}\)\{N}\zs\1/string/e 替换第N+1 pattern 语法复杂,能否解释一下呢?
不明白的可以去查vim自带的帮助
:h \%( #无计数分组
:h \{- #懒惰匹配
:h \zs #零宽度开始位置匹配

懒惰匹配和零宽匹配在不同的正则引擎中写法不一样,上面的是vim的写法
无计数分组也可以换成普通的计数分组,后面\1改成\2就是了
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#8

帖子 eexpress » 2014-10-30 9:39

还是perlre正宗。
● 鸣学
hjjdebug
帖子: 94
注册时间: 2009-04-21 9:48

Re: 正则表达式, 匹配字符 但不匹配第一个字符

#9

帖子 hjjdebug » 2014-10-30 16:07

受益! :em11 嵌套的pattern, 外面是\1, 里面是\2
回复