RegEx带位掩码?

问题描述:

我有一个部分二进制数据流,我想匹配时,在字符串中某个位置的某个字节中设置了某个位。RegEx带位掩码?

这在使用System.Text.RegularExpressions其被配置成与数量的图案.NET现有系统 - 当特定模式匹配,则匹配触发一个动作。

我接口到一个设备,其中的指标之一是唯一可用的位字段内。

我能看到的唯一的选择是符合整个等价类所有有位设置的字节数。

这是一个梅特勒 - 托利多量表接口。

流是这样的:

STX 
SWA 
SWB 
SWC 
WEIGHT (6 bytes ASCII) 
TARE (6 bytes ASCII) 
0x0D (CR) 
(Optional checksum) 

SWASWBSWC是状态字字节,我很感兴趣的SWB第3位。

他们总是设置位5:1,在所有这些状态字,所以它是一个空间(0x20)时,没有位被设置。所以实际上没有其他状态比特通过,SWB(0x50-01010000)和SPACE(0x20-00100000)之间的交替变化。实际上,比例也可能在我不在乎的其他状态中发送比特0和4关于。

所以我可以匹配..[\(all other equivalent characters]..{6}.{6}\r\0

+2

这是对我来说太抽象:)你能也许用一个例子澄清你的问题? – dasblinkenlight 2012-08-07 16:59:11

除非我明白你错了 - 你正在寻找应用上不是字符串的东西正则表达式(在你上面的例子,一个位域)。

this线链接到一个方法来应用规则表达式中的流匹配。然后您可以提供数据的匹配正确即

如果我理解正确的话,对于SWB唯一可能的值(二进制)001xx00x,你只需要使用正则表达式来区分001x000x(位3 = 0 )从001x100x(位3 = 1)。那是对的吗?如果是这样,那么你可以使用这个字符类检测时,位3 = 0

[\u0020\u0021\u0030\u0031] 

而这一次检测时,位3 = 1

​​

如果有更多不同的可能值对于SWB,那么它可能值得做更聪明的事情,但事实是,我不认为有这种需要。

+0

这是正确的。如果可能设置其他位,我将不得不添加其他等效字节。 – 2012-08-07 17:36:25

+0

实际上,我将不得不重新编译这个东西,使用一些替代的逻辑/配置,这个规模不依赖于简单的正则表达式,并试图找出如何在稍后将其重构为一致的配置。 – 2012-08-07 17:38:47

+0

@CadeRoux:Re:创建一个备用的非正则表达式配置:是的,我认为这是正确的选择。 :-) – ruakh 2012-08-08 12:25:42

当涉及到正则表达式,字符是一个不可分割的组成单位,所以你需要以一个字符内匹配位,创建一个字符类。

有两种方法可以在字符类中包含或排除一组字符 - 通过单独列出它们(如[asdfg]),或者指定一个范围(如[a-z])。

在最糟糕的情况下,您的组将包含128个覆盖单个位的元素。但是,如果您匹配较高位,则可以使用范围将连续字符组合在一起。

例如,匹配位8是

[\u0080-\u00FF] 

匹配位7是

[\u0040-\u007F\u00C0-\u00FF]` 

匹配位6是

[\u0020-\u003F\u0060-\u007F\u0060-\u007F\u00E0-\u00FF] 

等。

您已经从低速输入设备获得了一串短而长的固定长度的记录。使用正则表达式来读取/解析这个看起来像使用锤子来驱动螺丝钉。

为什么不只是将BinaryReader的数据读入自定义类并将其作为对象进行处理?更容易理解,更易于维护。

事情是这样的:

static void Main(string[] args) 
    { 
     using (Stream  s  = OpenStream()) 
     using (BinaryReader reader = new BinaryReader(s , Encoding.ASCII)) 
     { 
      foreach (ScaleReading reading in ScaleReading.ReadInstances(reader)) 
      { 
       if (!reading.IsValid) continue ; // let's just skip invalid data, shall we? 
       bool isInteresting = (reading.StatusB & 0x08) == 0x08 ; 
       if (isInteresting) 
       { 
        ProcessInterestingReading(reading) ; 
       } 
      } 
     } 

     return; 
    } 

其中ScaleReading看起来是这样的:

class ScaleReading 
{ 

    private ScaleReading(byte[] data , int checkSum) 
    { 
     this.Data    = data       ; 
     this.CheckSum   = checkSum      ; 
     this.ComputedCheckSum = ComputeCheckSumFromData(data) ; 

     this.STX  = data[0] ; 
     this.StatusA = data[1] ; 
     this.StatusB = data[2] ; 
     this.StatusC = data[3] ; 
     this.Weight = ToInteger(data, 4, 6) ; 
     this.Tare = ToInteger(data, 10,6) ; 
     this.CR  = data[16] ; 

    } 

    private int ToInteger(byte[] data , int offset , int length) 
    { 
     char[] chs = Encoding.ASCII.GetChars(data , offset , length) ; 
     string s  = new String(chs) ; 
     int value = int.Parse(s) ; 

     return value ; 
    } 

    private int ComputeCheckSumFromData(byte[] data) 
    { 
     //TODO: compute checksum from data octets 
     throw new NotImplementedException(); 
    } 

    public bool IsValid 
    { 
     get 
     { 
      bool isValid = ComputedCheckSum == CheckSum 
         && STX    == '\x0002' // expected STX char is actually STX 
         && CR    == '\r'  // expected CR char is actually CR 
         ; 
      return isValid ; 
     } 
    } 

    public byte[] Data    { get ; private set ; } 
    public int ComputedCheckSum { get ; private set ; } 
    public int CheckSum   { get ; private set ; } 

    public byte STX  { get ; private set ; } // ? 
    public byte StatusA { get ; private set ; } // might want to make each of status word an enum 
    public byte StatusB { get ; private set ; } // might want to make each of status word an enum 
    public byte StatusC { get ; private set ; } // might want to make each of status word an enum 
    public int Weight { get ; private set ; } 
    public int Tare { get ; private set ; } 
    public byte CR  { get ; private set ; } 

    public static ScaleReading ReadInstance(BinaryReader reader) 
    { 
     ScaleReading instance = null; 
     byte[]  data  = reader.ReadBytes(17); 

     if (data.Length > 0) 
     { 
      if (data.Length != 17) throw new InvalidDataException() ; 

      int checkSum = reader.ReadInt32() ; 
      instance  = new ScaleReading(data , checkSum); 

     } 

     return instance; 

    } 

    public static IEnumerable<ScaleReading> ReadInstances(BinaryReader reader) 
    { 
     for (ScaleReading instance = ReadInstance(reader) ; instance != null ; instance = ReadInstance(reader)) 
     { 
      yield return instance ; 
     } 
    } 

} 
+0

因为当我有其他工作要做时,我不想改变另一个古怪的书面传统程序。所以是的,现在它有一个特殊的模式来完成你写的东西,希望这个源代码是正确的版本,这个版本会很好的测试。 – 2012-08-07 19:37:25