不需要使用正则表达式或任何高级技巧来完成这个任务。我会简单地按冒号进行分割,并将结果传递给一个格式化字符串:
'PT%sM%sS' % "2:30".split(':') # => "PT2M30S"
在这种情况下,取模运算符如何工作?我以前从未见过这样的操作。
除非应用于数字,否则它不是“取模运算符”。它是一个名为“%”的字符串方法,相当于“format”或“sprintf”。有关更多信息,请参见
String.%
,然后是
Kernel::sprintf
,但基本上:
s | Argument is a string to be substituted. If the format
| sequence contains a precision, at most that many characters
| will be copied.
所以:
'%s' % 'foo' # => "foo"
'%5s' % 'foo' # => " foo"
'%-5s' % 'foo' # => "foo "
'%1s' % 'foo' # => "foo"
'%.1s' % 'foo' # => "f"
'%s = %s' % ['a', 1] # => "a = 1"
特别说明,在最后一个示例中,当将
1
插入字符串时会被转换为
"1"
。这种方式可以很有用,但并非将对象转换为字符串的唯一或者最好的方式。
最后,不要假设正则表达式是从字符串中提取信息的每个问题的最佳解决方法。如果你可以避免使用奇怪的变通方法,就使用内置的方法,例如
split
。
require 'fruity'
compare do
_split { 'PT%sM%sS' % "2:30".split(':') }
_regex { "2:30".sub(/(.*):(.*)/, "PT\\1M\\2S") }
end
这导致:
# >> Running each test 2048 times. Test will take about 1 second.
# >> _split is faster than _regex by 19.999999999999996% ± 10.0%
正则表达式灵活,但通常代价是更慢。
此外,我们看到许多误用gsub
而应该使用sub
的情况。相比之下,sub
的工作量要少得多;当sub
触发一次时,gsub
将继续循环直到达到字符串的末尾。即使在如"2:30"
这样的短字符串上也有可测量的差异:
compare do
_sub { "2:30".sub(/(.*):(.*)/, "PT\\1M\\2S") }
_gsub { "2:30".gsub(/(.*):(.*)/, "PT\\1M\\2S") }
end