Ruby 将字符串中的十进制数替换为等效的十六进制数

Ruby 将字符串中的十进制数替换为等效的十六进制数,ruby,regex,Ruby,Regex,我有一组巨大的字符串,如: // Register 10: typedef struct RegAddr_10 { uint8 something: 4; uint8 something_else: 4; } tRegAddr_10; 并希望将所有寄存器地址(以十进制数字给出)转换为十六进制。其他数字可以出现在每个typedef中;因此,我必须考虑 ReG/COD>部分作为一种定界符。该示例应导致: // Register 0x0A: typedef struct RegAddr_0x

我有一组巨大的字符串,如:

// Register 10:
typedef struct RegAddr_10
{
  uint8 something: 4;
  uint8 something_else: 4;
} tRegAddr_10;
并希望将所有寄存器地址(以十进制数字给出)转换为十六进制。其他数字可以出现在每个
typedef
中;因此,我必须考虑<代码> ReG/COD>部分作为一种定界符。该示例应导致:

// Register 0x0A:
typedef struct RegAddr_0x0A
{
  uint8 something: 4;
  uint8 something_else: 4;
} tRegAddr_0x0A;
我的解决办法是:

class String
  def convert_base(from, to)
    self.to_i(from).to_s(to)
  end
end  

new = text.gsub(/Reg\D*\d*/) do |number|
  number.gsub(/(\d+)/) {'0x'+$1.convert_base(10,16)}
end
这是可行的,但:

  • (如何)仅使用一个
    gsub
    就可以做到这一点
  • 如何使转换生成大写的2位十六进制数字,例如
    10
    → <代码>0x0A,而不是
    0xa
  • 代码

    R = /
        (?:                 # begin non-capture group
        ^                   # match beginning of line
        \/{2}\s+Register\s+ # match string
        |                   # or
        \s+RegAddr_         # match string
        |                   # or
        \s+tRegAddr_        # match string
        )                   # close non-capture group
        \K                  # discard everything matched so far
        \d+                 # match >= 1 digits
        /x                  # extended mode
    
    def replace_with_hex(str)
      str.gsub(R) { |s| "0x%02X" % s }
    end
    
    str = <<_ 
    // Register 10:
    typedef struct RegAddr_10
    {
      uint8 something: 4;
      uint8 something_else: 4;
    } tRegAddr_10;
    _
    
    puts replace_with_hex(str)
    
    百分比字符后面的格式字符串部分是:
    0
    ,表示用零填充左边,
    2
    表示字段宽度,
    X
    表示转换为十六进制,大写字母
    A
    -
    F
    X
    表示小写)

    示例

    R = /
        (?:                 # begin non-capture group
        ^                   # match beginning of line
        \/{2}\s+Register\s+ # match string
        |                   # or
        \s+RegAddr_         # match string
        |                   # or
        \s+tRegAddr_        # match string
        )                   # close non-capture group
        \K                  # discard everything matched so far
        \d+                 # match >= 1 digits
        /x                  # extended mode
    
    def replace_with_hex(str)
      str.gsub(R) { |s| "0x%02X" % s }
    end
    
    str = <<_ 
    // Register 10:
    typedef struct RegAddr_10
    {
      uint8 something: 4;
      uint8 something_else: 4;
    } tRegAddr_10;
    _
    
    puts replace_with_hex(str)
    
    备选方案

    如果你不那么挑剔:

    R = /
        [\s|t] # match whitespace or t
        Reg\D+ # match string
        \K     # discard everything matched so far
        \d+    # match >= 1 digits
        /x     # extended mode
    
    同样有效

    您还可以将
    的操作行替换为\u hex

    str.gsub(R, "0x%02X" % $~[0])
    

    为什么要在它前面加上
    '0x0x'
    ?@sawa:因为这是一个复制粘贴错误;-)修正后,你可能会考虑选择你觉得最有用的答案,如果有价值的话。哦,等等,sawa删除了他的答案,所以我的答案是唯一剩下的。@Cary:是的,很遗憾sawa删除了他的答案,而不是改进它:-(当然,如果没有其他人有答案,从逻辑上讲,我将不得不选择你的答案作为最有帮助的答案;-)谢谢你的解决方案,特别是对它的一些评论!:-)