从 ruby 中的数组中仅获取十六进制值(字节)
Get only Hexadecima values (bytes) from array in ruby
我有以下数组,表示 ASCII 和非 ASCII 字符的十进制值。
a=[32, 57, 50, 32, 56, 51, 32, 65, 52, 130, 0, 101, 131, 69, 72, 38, 146, 89, 9]
转换为 char 看起来像这样
a.map{|b| b.chr}
=> [" ", "9", "2", " ", "8", "3", " ", "A", "4", "\x82", "\x00", "e", "\x83", "E", "H", "&", "\x92", "Y", "\t"]
并加入以创建带字节的字符串(十六进制数对,[0-9A-F])我这样做:
a.map{|b| b.chr}.join
=> " 92 83 A4\x82\x00e\x83EH&\x92Y\t"
然后我想删除从第一个非 ASCII 值 \x82 开始的字符串,我喜欢这样做,但没有任何反应。
a.map{|b| b.chr}.join.gsub(/\x.*/,"")
=> " 92 83 A4\x82\x00e\x83EH&\x92Y\t"
我的预期输出是只有以下十六进制数:
92 83 A4
我该怎么做?
感谢您的帮助。
更新
使用像下面这样的更大的数组进行测试,我发现只有@rewritten 的解决方案的输出是正确的。这个新数组的输出是 " 92 83 49 26 92 59 00"
a=[32, 57, 50, 32, 56, 51, 32, 52, 57, 32, 50, 54, 32, 57, 50, 32, 53, 57,
32, 48, 48, 0, 0, 0, 0, 2, 130, 0, 0, 8, 254, 70, 124, 0, 6, 0, 3, 0, 3,
27, 0,2, 27, 3, 0, 227, 7, 1, 14, 17, 33, 0, 28, 14, 47, 38, 146, 89, 9]
a.map(&:chr).join.match(/^( \X\X)+/)[0] # rewritten's solution
a.map(&:chr).take_while(&"\x80".method(:>)).join # Aleksei's solution
a.map(&:chr).take_while(&:ascii_only?).join # cremno's solution
irb(main): a.map(&:chr).join.match(/^( \X\X)+/)[0]
=> " 92 83 49 26 92 59 00"
irb(main): a.map(&:chr).take_while(&"\x80".method(:>)).join
=> " 92 83 49 26 92 59 00\x00\x00\x00\x00\x02"
irb(main): a.map(&:chr).take_while(&:ascii_only?).join
=> " 92 83 49 26 92 59 00\x00\x00\x00\x00\x02"
感谢大家的帮助。
在将数组连接成字符串之前过滤掉它:
[" ", "9", "2", " ", "8", "3", " ", "A", "4", "\x82", "\x00"].
take_while(&"\x80".method(:>))
#⇒ [" ", "9", "2", " ", "8", "3", " ", "A", "4"]
然后对结果数组做任何你想做的事。
鉴于评论,我假设您真的想询问匹配模式 "space, hex, hex" 直到第一个不匹配。
这就像
a.map(&:chr).join.match(/^( \X\X)+/)[0]
它使用特殊的\X
占位符来匹配u̶p̶p̶e̶r̶c̶a̶s̶e̶十六进制数字(0-9,A-F,a-f)的正则表达式。
附加信息:
再次根据我对问题的解释,如果原始数组很长(或流),则无需全部消耗。你最好尽快停止生成字符:
hexs = "0123456789ABCDEF".split.map(&:ord)
a.
lazy.
each_slice(3).
take_while { |spc, h1, h2| spc == 32 && hexs.include?(h1) && hexs.include?(h2) }.
flat_map(&:chr).
to_a.
join
这样,您的整数数组的任何部分都不会被考虑在内。
我有以下数组,表示 ASCII 和非 ASCII 字符的十进制值。
a=[32, 57, 50, 32, 56, 51, 32, 65, 52, 130, 0, 101, 131, 69, 72, 38, 146, 89, 9]
转换为 char 看起来像这样
a.map{|b| b.chr}
=> [" ", "9", "2", " ", "8", "3", " ", "A", "4", "\x82", "\x00", "e", "\x83", "E", "H", "&", "\x92", "Y", "\t"]
并加入以创建带字节的字符串(十六进制数对,[0-9A-F])我这样做:
a.map{|b| b.chr}.join
=> " 92 83 A4\x82\x00e\x83EH&\x92Y\t"
然后我想删除从第一个非 ASCII 值 \x82 开始的字符串,我喜欢这样做,但没有任何反应。
a.map{|b| b.chr}.join.gsub(/\x.*/,"")
=> " 92 83 A4\x82\x00e\x83EH&\x92Y\t"
我的预期输出是只有以下十六进制数:
92 83 A4
我该怎么做?
感谢您的帮助。
更新
使用像下面这样的更大的数组进行测试,我发现只有@rewritten 的解决方案的输出是正确的。这个新数组的输出是 " 92 83 49 26 92 59 00"
a=[32, 57, 50, 32, 56, 51, 32, 52, 57, 32, 50, 54, 32, 57, 50, 32, 53, 57,
32, 48, 48, 0, 0, 0, 0, 2, 130, 0, 0, 8, 254, 70, 124, 0, 6, 0, 3, 0, 3,
27, 0,2, 27, 3, 0, 227, 7, 1, 14, 17, 33, 0, 28, 14, 47, 38, 146, 89, 9]
a.map(&:chr).join.match(/^( \X\X)+/)[0] # rewritten's solution
a.map(&:chr).take_while(&"\x80".method(:>)).join # Aleksei's solution
a.map(&:chr).take_while(&:ascii_only?).join # cremno's solution
irb(main): a.map(&:chr).join.match(/^( \X\X)+/)[0]
=> " 92 83 49 26 92 59 00"
irb(main): a.map(&:chr).take_while(&"\x80".method(:>)).join
=> " 92 83 49 26 92 59 00\x00\x00\x00\x00\x02"
irb(main): a.map(&:chr).take_while(&:ascii_only?).join
=> " 92 83 49 26 92 59 00\x00\x00\x00\x00\x02"
感谢大家的帮助。
在将数组连接成字符串之前过滤掉它:
[" ", "9", "2", " ", "8", "3", " ", "A", "4", "\x82", "\x00"].
take_while(&"\x80".method(:>))
#⇒ [" ", "9", "2", " ", "8", "3", " ", "A", "4"]
然后对结果数组做任何你想做的事。
鉴于评论,我假设您真的想询问匹配模式 "space, hex, hex" 直到第一个不匹配。
这就像
a.map(&:chr).join.match(/^( \X\X)+/)[0]
它使用特殊的\X
占位符来匹配u̶p̶p̶e̶r̶c̶a̶s̶e̶十六进制数字(0-9,A-F,a-f)的正则表达式。
附加信息:
再次根据我对问题的解释,如果原始数组很长(或流),则无需全部消耗。你最好尽快停止生成字符:
hexs = "0123456789ABCDEF".split.map(&:ord)
a.
lazy.
each_slice(3).
take_while { |spc, h1, h2| spc == 32 && hexs.include?(h1) && hexs.include?(h2) }.
flat_map(&:chr).
to_a.
join
这样,您的整数数组的任何部分都不会被考虑在内。