1

我正在尝试通过在子字符串的每个部分中插入一个连字符来将 UUID 变成一个正确符合的 UUID。

test = "CB13DBB20A9945CC86F11914C979C761"
#The first one will return '----' so essentially the $1 to $5 are returned as emptys
test.sub(/(\h{8})(\h{4})(\h{4})(\h{4})(\h{12})/, "#{$1}-#{$2}-#{$3}-#{$4}-#{$5}")
#Returns the ideal result of CB13DBB2-0A99-45CC-86F1-1914C979C761
test.sub(/(\h{8})(\h{4})(\h{4})(\h{4})(\h{12})/, "#{$1}-#{$2}-#{$3}-#{$4}-#{$5}")

如您所见,该函数的第一次运行不起作用,但第二次运行。任何想法都会很棒。作为附加信息,

test.match(/(\h{8})(\h{4})(\h{4})(\h{4})(\h{12})/){|m| "#{$1}-#{$2}-#{$3}-#{$4}-#{$5}"}

将在第一次工作。单引号和双引号不影响任何东西。

4

4 回答 4

4

While this can be accomplished using regex, I'd go with substrings:

require 'pp'

uuid = 'CB13DBB20A9945CC86F11914C979C761'
pp [uuid[0, 8], uuid[8, 4], uuid[12, 4], uuid[16, 4], uuid[20, 12]]
# => ["CB13DBB2", "0A99", "45CC", "86F1", "1914C979C761"]

puts [
  uuid[0, 8], uuid[8, 4], uuid[12, 4], uuid[16, 4], uuid[20, 12]
].join('-')
# => CB13DBB2-0A99-45CC-86F1-1914C979C761

Because the use of offsets and lengths can be a bit of a chore when writing that code, here's an alternate using unpack with only the lengths:

lengths = [8, 4, 4, 4, 12]
uuid.unpack(lengths.map{ |l| "a#{ l }" }.join).join('-')
# => "CB13DBB2-0A99-45CC-86F1-1914C979C761"
于 2012-11-20T15:56:41.377 回答
3

像这样引用模式匹配。

test.sub(/(\h{8})(\h{4})(\h{4})(\h{4})(\h{12})/, '\1-\2-\3-\4-\5')

Ruby Docs 中解释了您看到这种行为的原因:

如果替换是一个字符串,它将被替换为匹配的文本。它可能包含对模式捕获组的反向引用,格式为 \d,其中 d 是组号,或 \k,其中 n 是组名。如果它是双引号字符串,则两个反向引用都必须以附加的反斜杠开头。但是,在替换中,特殊匹配变量(例如 &$)不会引用当前匹配

于 2012-11-20T15:36:59.627 回答
1

在您的示例中, $1...$5 在替换之前在字符串中被替换。

如果您想在替换期间对它们进行评估,请改用块形式:

test.sub(/(\h{8})(\h{4})(\h{4})(\h{4})(\h{12})/) { "#{$1}-#{$2}-#{$3}-#{$4}-#{$5}" }
于 2012-11-20T15:37:06.097 回答
0

FWIW,Ruby 有 SecureRandom 来提供 uuid

require 'securerandom'
p SecureRandom.uuid #"dd1f58f8-8c42-47e0-9c08-a8d5c191c9c3"

将绳子切成碎片很容易完成String#unpack

test = "CB13DBB20A9945CC86F11914C979C761"
p test.unpack("A8A4A4A4A8").join('-') #"CB13DBB2-0A99-45CC-86F1-1914C979"
于 2012-11-20T17:13:54.183 回答