Regex для получения байтов между двоичным содержимым - PullRequest
0 голосов
/ 26 января 2019

У меня есть следующие 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>'

Я думаю, что мне нужно только правильное регулярное выражение или есть лучший способ извлечь нужные значения без использования регулярного выражения?

Спасибо за любую помощь

Ответы [ 2 ]

0 голосов
/ 26 января 2019
#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"
0 голосов
/ 26 января 2019
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}), за которыми следует пробел, за которым следуют две шестнадцатеричные цифры, эти три символа в группе совпадают один или несколько раз (+), (?: \h{2}) будучи группой без захвата .

...