Ruby - 在中间行替换字符?

时间:2013-12-26 01:16:10

标签: ruby regex

您好我正在阅读有关Ruby的教科书,并发现我可以使用

.sub(/^../,'hello') 
.sub(/..$/,'hello')

替换第一行中的第一个或最后两个字符。

我想知道如果有多行,我怎么能用其他行代替。

例如

x = <<end_string
aaa
bbb
ccc
ddd
end_string

将'bb'更改为'某事'或'cc'。

当我尝试

.sub(/\n^../,'hello')

结果是;

aaaHellob
ccc
ddd

更改了第二行中的前两个字符,但不知何故,第二行被移动到第一行。

所以我的问题是,如何更改(替换)某一行中的字符? 如果你能解释我为什么得到这个结果,我会非常感激。

谢谢。

2 个答案:

答案 0 :(得分:2)

你得到了那个结果,因为sub替换了它匹配的字符串。由于您匹配换行符(并且未在替换文本中使用换行符),因此您的字符串之后的换行符较少。

简单的解决方案是在替换文本中使用换行符:

irb> puts x.gsub(/\n../, "\nHELLO")
aaa
HELLOb
HELLOc
HELLOd
#=> nil 

如果您不想在最后一行操作,可以使用否定前瞻:

irb> puts x.gsub(/\n..(?!.*\Z)/, "\nHELLO")
aaa
HELLOb
HELLOc
ddd
#=> nil 

您可以使用正面的lookbehind来避免在替换字符串中使用换行符

irb> puts x.gsub(/(?<=\n)..(?!.*\Z)/, "HELLO")
aaa
HELLOb
HELLOc
ddd
#=> nil 

lookahead和lookbehinds的语法有点奇怪,但它们只是将模式(匹配并消耗一些文本长度)转换为与文本中零宽度位置匹配的东西。在正则表达式中已经有零宽度位置匹配,使用:

  • ^作为行首
  • $代表行
  • \b用于字边界
  • \A表示字符串的开头
  • \Z结束字符串

Lookaheads和lookbehinds让你自己定义:

  • (?=PAT)〜在PAT
  • 之前匹配
  • (?<=PAT)〜在PAT
  • 之后立即匹配
  • (?!PAT)〜匹配任何地方,但在PAT
  • 之前
  • (?<!PAT)〜匹配任何地方,但在PAT
  • 之后

答案 1 :(得分:0)

分割线,替换特定线和连接线怎么样?

>> x = <<end_string
aaa
bbb
ccc
ddd
end_string
>> lines = x.split("\n")
>> lines[1].sub!(/../, 'hello')
>> lines = lines.join("\n")
>> puts lines
aaa
hellob
ccc
ddd