Ruby正则表达式消除了新的行,直到。要么 ?或大写字母

时间:2016-10-06 17:20:50

标签: ruby regex newline

我想用我的字符串做以下事情:

line1= "You have a house\nnext to the corner."

如果句子在点或问号或大写字母后的新行中没有完成,则消除\n,因此在这种情况下所需的输出将是:

"You have a house next to the corner.\n"

另一个例子,这次是问号:

"You like baggy trousers,\ndon't you?

应该成为:

"You like baggy trousers, don't you?\n".

我试过了:

line1.gsub!(/(?<!?|.)"\n"/, " ") 
紧接在\ n之前的

(?<!?|.) \ n一定不能有问号(?)或逗号

但是我收到以下语法错误:

SyntaxError: (eval):2: target of repeat operator is not specified: /(?<!?|.)"\n"/

对于句子中间有一个大写字母的句子,在大写字母之前插入一个\ n所以句子:

"We were winning The Home Secretary played a important role." 

应该成为:

"We were winning\nThe Home Secretary played a important role." 

3 个答案:

答案 0 :(得分:1)

你快到了。您需要a)同时转义?.以及b)删除表达式中\n周围的引号:

line1= "You have a house\nnext to the corner.\nYes?\nNo."
line1.gsub!(/(?<!\?|\.)\s*\n\s*/, " ")
#⇒ "You have a house next to the corner.\nYes?\nNo."

如果您想要跟踪\n,请稍后添加:

line1.gsub! /\Z/, "\n"
#⇒ "You have a house next to the corner.\nYes?\nNo.\n"

答案 1 :(得分:1)

这样做的简单方法是用空格替换所有嵌入的新行,这有效地连接线段,然后修复线端。没有必要担心标点符号,并且没有必要使用(或维护)正则表达式。

你可以通过很多方式实现这一目标,但我会使用:

sentences = [
  "foo\nbar",
  "foo\n\nbar",
  "foo\nbar\n",
]

sentences.map{ |s| s.gsub("\n", ' ').squeeze(' ').strip + "\n" }
# => ["foo bar\n", "foo bar\n", "foo bar\n"]

此处map区域内发生了什么:

s                # => "foo\nbar", "foo\n\nbar", "foo\nbar\n"
.gsub("\n", ' ') # => "foo bar", "foo  bar", "foo bar "
.squeeze(' ')    # => "foo bar", "foo bar", "foo bar "
.strip           # => "foo bar", "foo bar", "foo bar"
+ "\n"           

答案 2 :(得分:1)

注意:答案并不是要提供一种删除句子中不必要的换行符号的通用方法,它只是为了OP目的,只删除或插入字符串中特定位置的换行符

由于您需要以不同方式替换不同场景中的匹配,因此您应该考虑采用两步法。

.gsub(/(?<![?.])\n/, ' ')

这一行将替换所有不在?.之前的换行符(如果在当前位置之前存在子模式匹配,则(?<![?.])是否为匹配导致失败的匹配字符串)。

第二步是

.sub(/(?<!^) *+(?=[A-Z])/, '\n')

.sub(/(?<!^) *+(?=\p{Lu})/, '\n')

它将匹配0+空格( *+)(占有率,没有回溯到空间模式中)不在行的开头(由于(?<!^)负面的后观,替换{{ 1}} ^匹配整个字符串的开头),然后跟一个大写字母(\A是一个正向前瞻,需要一个模式出现在当前位置之后右)。