简体   繁体   English

如何最好地从 ruby 中的字符串中获取所有格式序列键?

[英]How best to get all the format sequence keys from a string in ruby?

When given a string that is intended to be formatted with a hash of values to write into the string, is there a clean way to get all the keys that string is expecting values for?当给定一个字符串,该字符串打算用 hash 的值格式化以写入字符串时,是否有一种干净的方法来获取字符串期望值的所有键?

I'm putting together text in a situation where there is a lot of room for customization, and several options for dynamic values to insert into the text.我在有很大自定义空间的情况下将文本放在一起,并且有几个动态值选项可以插入到文本中。 Some of the values are more expensive to get than others, so I'd like to be able to prepare my hash to send in to % to only include the values that are needed in the string.有些值比其他值更昂贵,所以我希望能够准备我的 hash 发送到%以仅包含字符串中需要的值。

Ideally I'd be able to query the system that performs the formatting on the string, but I'm not seeing any documentation of such an interface.理想情况下,我能够查询对字符串执行格式设置的系统,但我没有看到此类接口的任何文档。 What I'd like is something like:我想要的是这样的:

"Your request for %{item} is at position %<pos>d".formatting_keys
>>> [:item, :pos]

When passing a hash to String#% , it will call the hash's default proc if a key is missing.将 hash 传递给String#%时,如果缺少键,它将调用散列的默认过程。 You could utilize this behavior and make the proc sneakily collect the passed keys:您可以利用此行为并让 proc 偷偷收集传递的密钥:

def format_keys(format_string)
  keys = []
  format_string % Hash.new { |_, k| keys << k ; 0 }
  keys
end

format_keys("Your request for %{item} is at position %<pos>d")
#=> [:item, :pos]

Note that the proc's return value has to be a valid object for the various field types.请注意,对于各种字段类型,proc 的返回值必须是有效的 object。 I'm using 0 here which seems to work fine.我在这里使用0似乎工作正常。

I'd like to be able to prepare my hash to send in to % to only include the values that are needed in the string.我希望能够准备我的 hash 发送到 % 以仅包含字符串中需要的值。

Instead of a Hash, use an object that does the calculation on demand.使用按需计算的 object 而不是 Hash。 That will be useful everywhere.这将在任何地方都有用。

Use string interpolation to call the methods instead of format sequences.使用字符串插值来调用方法而不是格式化序列。

class Whatever
  def item
    @item ||= calculate_item
  end

  def pos
    @pos ||= calculate_pos
  end

  private

  def calculate_item
    # do something expensive
  end

  def calculate_pos
    # do something expensive
  end
end

obj = Whatever.new
puts "Your request for #{obj.item} is at position #{obj.pos.to_i}"

Using Ruby's own sequence parsing as per https://stackoverflow.com/a/74728162 is ideal, but you can also do your own:根据https://stackoverflow.com/a/74728162使用 Ruby 自己的序列解析是理想的,但您也可以自己做:

class String
  def format_keys
    scan(
      /
        (?<!%) # don't match escaped sequence starts, e.g. "%%{"
        (?:
          (?<=%\{) [^\}]+ (?=\}) # contents of %{...}
          |                      # OR
          (?<=%\<) [^\>]+ (?=\>) # contents of %<...>
        )
      /x
    )
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM