假设我有一个字符串"2foo9 8bar5"
.我需要交换两个数字来包装每个单词。结果应如下所示"9foo2 5bar8"
。
我可以用以下代码做到这一点。
def swap_num(str)
str = str.gsub(/(d)(D+)(d)/, '321')
end
但是如果我有这样的字符串"2foo9 8bar5 3+=_1"
,这个swap_num
方法也会交换最后一部分的数字"3+=_1"
,这不是我想要的。我只想交换包装单词的数字,而不是任何字符。
我尝试了以下方法,但没有奏效。
def swap_num(str)
str = str.gsub(/(d)([a-zA-Z]+)(d)/, '321')
end
有什么方法可以用简单的正则表达式做到这一点吗?谢谢!
更新:
对不起,伙计们。我犯了一个错误,str = str.gsub(/(d)([a-zA-Z]+)(d)/, '321')
实际上达到了我的目的。但是如果我像这样使用双引号"321"
就行不通了.
谢谢,@Robin指出我的原始代码确实有效。还要感谢@Cary Swoveland 和 @Andie2302 为我提供了 2 个新的解决方案!真的很感激!
这样做:
R = /
b # match a word boundary
(d+) # match ?= 1 digits, capture in group #1
([a-z]+) # match >= 1 lower case letters, capture in group #2
(d+) # match >= 1 digits, capture in group #3
b # match a word boundary
/ix # case indifferent (/i) and extended mode (/x)
def flip_numbers(str)
str.gsub(R) { $3+$2+$1 }
end
flip_numbers("2foo9 8bar5")
#=> "9foo2 5bar8"
flip_numbers("233foo91 8bar5")
#=> "91foo233 5bar8"
flip_numbers("2foo9 8bar5 3+=_1")
#=> "9foo2 5bar8 3+=_1"
flip_numbers("a2foo9 8bar5 3bat7c")
#=> "a2foo9 5bar8 3bat7c"
请注意,在上一个示例中,由于单词边界要求,a2foo9
和3bat7c
中的数字不会交换。
每个匹配的字符串都传递给 gsub
的块,该块计算该字符串的替换。我们可以将块写为:
{ |s| <code here> }
其中块变量等于匹配的字符串。在第一个示例中,这将是:
s = "2foo9"
我们希望将其替换为:
"9foo2"
三个捕获组的内容包含在全局变量中:
$1 #=> "9"
$2 #=> "foo"
$3 #=> "2"
因此,替换字符串为:
$3+$2+$1 #=> "2foo9".
因此,该块被写入:
{ |s| $3+$2+$1 }
但是由于我们在此计算中不使用块变量s
,因此我们可以从块中省略|s|
。这是一个很好的做法,因为减少了出错的机会,并且还告诉读者不使用块变量。
表达式 $3+$2+$1
可以改为 gsub
的参数,但在这种情况下,它必须写成:
"2foo9 8bar5".gsub(R, '321')
#=> "9foo2 5bar8"
或
"2foo9 8bar5".gsub(R, "\3\2\1")
#=> "9foo2 5bar8"
这里的选择纯粹是风格上的。
工作正则表达式是:
(d)(p{L}+)(d)
str = str.gsub(/(d)(p{L}+)(d)/, '321')
\p{L} ...匹配 Unicode 类别"字母"中的字符(任何语言的任何字母字符)