我有以下3个包含二进制数据的字符串。
s1="\t 28890\tABGT\tXYZW\t 94 23 08 92 00 00 00 EC 02 10 00 E2 00 4B\t\x00\x00\x00\x00\x01\f".force_encoding("ASCII-8BIT")
s2=" \t0000013\t123\t9886\t 95 83 49 26 0E 82 00 A6 08 02 06 C0\x00\x00\x00\x00\x02\xB2\x00\x00\x00\x00\b\xFEF".force_encoding("ASCII-8BIT")
s3=" \t0000013\t123\t9HN3\t 95 83 49 26 0E 82 00 A6 08 02 06 C0\xA1\x02\x00\x00\x02\xB2\b\xFEF".force_encoding("ASCII-8BIT")
我有以下3个类似的正则表达式来获取*\t
和以\
开头的内容(即\ t,\ x00,\ xB2,\ xFEF)之间的字节
s1[/(?<=[A-Z]{4}\t ).+?(?=\t)/]
s2[/(?<=[0-9]{4}\t ).+?(?=\x00)/]
s3[/(?<=.+\t ).+?(?=\x..)/]
前2个正则表达式适用于字符串s1和s2,但是更通用的正则表达式如何匹配这3种情况?
我尝试了正则表达式s3[/(?<=.+\t ).+?(?=\x..)/]
,但下面出现错误。
irb(main):> s1[/(?<=[A-Z]{4}\t ).+?(?=\t)/]
=> "94 23 08 92 00 00 00 EC 02 10 00 E2 00 4B"
irb(main):> s2[/(?<=[0-9]{4}\t ).+?(?=\x00)/]
=> "95 83 49 26 0E 82 00 A6 08 02 06 C0"
irb(main):> s3[/(?<=.+\t ).+?(?=\x..)/]
SyntaxError: (irb):4953: invalid hex escape
s3[/(?<=.+\t ).+?(?=\x..)/]
^
invalid pattern in look-behind: /(?<=.+\t ).+?(?=..)/
from /usr/bin/irb:11:in `<main>'
我认为我只需要正确的正则表达式,或者有更好的方法可以在不使用正则表达式的情况下提取所需的值?
感谢您的帮助
答案 0 :(得分:2)
R = /\h{2}(?: \h{2})+/
def extract(str)
str[R]
end
extract(s1)
#=> "94 23 08 92 00 00 00 EC 02 10 00 E2 00 4B"
extract(s2)
#=> "95 83 49 26 0E 82 00 A6 08 02 06 C0"
extract(s3)
#=> "95 83 49 26 0E 82 00 A6 08 02 06 C0"
正则表达式为:“匹配两个十六进制数字(\h{2}
),后跟一个空格,后跟两个十六进制数字,这三个字符作为一个组匹配一次或多次(+
),{ {1}}是一个非捕获组。
答案 1 :(得分:2)
#ruby 2.3.1
xs = ["\t 28890\tABGT\tXYZW\t 94 23 08 92 00 00 00 EC 02 10 00 E2 00 4B\t\x00\x00\x00\x00\x01\f".force_encoding("ASCII-8BIT"),
" \t0000013\t123\t9886\t 95 83 49 26 0E 82 00 A6 08 02 06 C0\x00\x00\x00\x00\x02\xB2\x00\x00\x00\x00\b\xFEF".force_encoding("ASCII-8BIT"),
" \t0000013\t123\t9HN3\t 95 83 49 26 0E 82 00 A6 08 02 06 C0\xA1\x02\x00\x00\x02\xB2\b\xFEF".force_encoding("ASCII-8BIT"),
"\t 28890\tABGT\tXYZW\t 94\t\x00\x00\x00\x00\x01\f".force_encoding("ASCII-8BIT"),
" \t0000013\t123\t9HN3\t 95 83 49 26 0E 82 00 A6 08 02 06 C0".force_encoding("ASCII-8BIT")]
r = /
(?<= # start of lookbehind: asserts that what immediately precedes the current position in the string are
[[:alnum:]]{4}\t[ ] # a space character, and a tab character and then four alphanumeric characters
) # end of lookbehind
[[:xdigit:]]{2} # match two hex digits
(?: # start non-capture group
[ ] # match a space character
[[:xdigit:]]{2} # match two hex digits
)* # end the non-capture group and match it zero or more times
/x # free-spacing mode
xs.map { |x| p x[r] }
输出:
"94 23 08 92 00 00 00 EC 02 10 00 E2 00 4B"
"95 83 49 26 0E 82 00 A6 08 02 06 C0"
"95 83 49 26 0E 82 00 A6 08 02 06 C0"
"94"
"95 83 49 26 0E 82 00 A6 08 02 06 C0"