用十六进制等效替换字符串中的十进制数

时间:2015-09-29 14:53:21

标签: ruby regex

我有一大堆字符串,如:

// Register 10:
typedef struct RegAddr_10
{
  uint8 something: 4;
  uint8 something_else: 4;
} tRegAddr_10;

并希望将所有寄存器地址(以十进制数给出)转换为十六进制。其他数字可以在每个typedef内出现;因此,我必须将Reg部分视为一种分隔符。该示例应该导致:

// 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

它有效,但是:

  1. (如何)只能使用一个gsub执行此操作?
  2. 如何使转换以大写形式生成2位十六进制数字,例如100x0A,而非0xa

1 个答案:

答案 0 :(得分:2)

<强>代码

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

String#%格式字符串中跟随字符百分比的部分是:0,表示填充左侧为零,2表示字段宽度,X表示要转换使用大写字母A - F的大写字母(小写x)。

示例

str = <<_ 
// Register 10:
typedef struct RegAddr_10
{
  uint8 something: 4;
  uint8 something_else: 4;
} tRegAddr_10;
_

puts replace_with_hex(str)

打印:

// Register 0x0A:
typedef struct RegAddr_0x0A
{
  uint8 something: 4;
  uint8 something_else: 4;
} tRegAddr_0x0A;

<强>替代

如果你不那么挑剔:

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

也可以。

您还可以将replace_with_hex的操作行更改为:

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