Banoona
Banoona

Reputation: 1650

RegEx to match field values in a block (tf.exe perm) TFS 2008

I am trying to write a regex to extract the blocks of information below, as well as the fields within each block. I am using Powershell.

I want to capture all "Server Item" blocks, and the following information for each one:

Server Item (1 **or more** of these items in the text)

   Identity (1 **or more** of these Identity items per Server Item)

    -- Allow (Each Identity contains **one** Allow)

    -- Deny (Each Identity contains **one** Deny)

    -- Allow (Inherited) (Each Identity contains **one** Allow (Inherited))

    -- Deny (Inherited) (Each Identity contains **one** Deny (Inherited))

The information is hierarchical (one to many for each heading to its children), as you can see.

Any answers greatly appreciated!

Sample Input text, below:

Server item: $/The/Path/Goes/Here
   Identity: Identity Number One (TYPE A)
      Allow:      
      Deny:
      Allow (Inherited): Read, Write, Checkin, Label
                         Lock, CheckinOther
      Deny (Inherited):  
====================================================================

Server item: $/The/Other/Path/Goes/Here
   Identity: Identity Number One (TYPE B)
      Allow: Read, Write, Checkin, Label
                         Lock, CheckinOther     
      Deny:
      Allow (Inherited): 
      Deny (Inherited):  
====================================================================

etc.

I have tried something like the following:

$thePattern = @"
(?<serveritem>Server item:(.|\n)*?=)
"@
$myText -match $thePattern

This does not capture all of the items and just gives me the first one! Also, how do I capture the Identity and field information for each Server item --> Identities --> Permissions?

The desired output would be to capture all of the Server items, and to be able to access each of the Identities, and for each Identity, to be able to access the permissions (Allow, Deny etc) The objective is to iterate through the blocks so as to add the information to a database for querying.

I am working on this with the following modification.

Upvotes: 1

Views: 111

Answers (2)

goTo-devNull
goTo-devNull

Reputation: 9372

Assuming the (text) input is as consistently formatted as your sample, you can extract the information you need with much simpler regular expressions if you break up the input and iterate in a line-by-line fashion.

For example, given the following input with "1 or more of these Identity items per Server Item":

Server item: $/The/Path/Goes/Here
   Identity: Identity Number One (TYPE A)
      Allow:      
      Deny:
      Allow (Inherited): Read, Write, Checkin, Label
                         Lock, CheckinOther
      Deny (Inherited):  
====================================================================

Server item: $/The/Other/Path/Goes/Here
   Identity: Identity Number One (TYPE B)
      Allow: Read, Write, Checkin, Label
                         Lock, CheckinOther     
      Deny:
      Allow (Inherited): 
      Deny (Inherited):  
====================================================================

Server item: $/The/Other/other/Path/Goes/Here
   Identity: Identity Number One (TYPE C)
      Allow: Read, Write, Checkin, Label
                         Lock, CheckinOther     
      Deny:
      Allow (Inherited): 
      Deny (Inherited):  
   Identity: Identity Number One (TYPE D)
      Allow: Read, Write, Checkin, Label
                         Lock, CheckinOther     
      Deny:
      Allow (Inherited): 
      Deny (Inherited): 

To get the hierarchical information:

# used .txt file for example 
$lines = Get-Content $path;
$result = @{};
$serverItem = '';
$identityItem = '';
$currentKey = '';
foreach ($line in $lines) {
    $key, $value = [Regex]::Split($line.Trim(), '\s*:\s*', 2);
    switch -Regex ($key) {
        '^server item' { 
            $serverItem = $value;
            $result.$serverItem = @{};
            continue;
        }
        '^identity' { 
            $identityItem = $value;
            $result.$serverItem.$identityItem = @{};
            continue;
        }
        '^[A-Za-z]+' {
            if ($value -ne $null) {
                $currentKey = $key;
                $result.$serverItem.$identityItem.$key = $value;
            } else {
                $result.$serverItem.$identityItem.$currentKey += ", $key";
            }
        }
    }
}

Upvotes: 1

Chrᴉz remembers Monica
Chrᴉz remembers Monica

Reputation: 1904

Server item:(.*?)[\r\n]+ *Identity:(.*?)[\r\n]+ *Allow: ?(.*?)[\r\n]+ *Deny: ?(.*?)[\r\n]+ *Allow \(Inherited\): ?(.*?)[\r\n]+ *Deny \(Inherited\): ?(.*?)([\r\n]+=|$)

with options /gs (global+singleline)

Matches on

Server item: $/The/Path/Goes/Here
   Identity: Identity Number One (TYPE A)
      Allow:      
      Deny:
      Allow (Inherited): Read, Write, Checkin, Label
                         Lock, CheckinOther
      Deny (Inherited):  
====================================================================

Server item: $/The/Other/Path/Goes/Here
   Identity: Identity Number One (TYPE B)
      Allow: Read, Write, Checkin, Label
                         Lock, CheckinOther     
      Deny:
      Allow (Inherited): 
      Deny (Inherited):  

Match1

  • Group 1: $/The/Path/Goes/Here
  • Group 2: Identity Number One (Type a)
  • Group 3: [empty]
  • Group 4: [empty]
  • Group 5: Read, Write, Checkin, Label [NEWLINE + SPACES] Lock, CheckinOther
  • Group 6: [empty]

Match2

  • Group 1: $/The/Other/Path/Goes/Here
  • Group 2: Identity Number One (Type b)
  • Group 3: Read, Write, Checkin, Label [NEWLINE + SPACES] Lock, CheckinOther
  • Group 4: [empty]
  • Group 5: [empty]
  • Group 6: [empty]

Tested with regex101

Upvotes: 1

Related Questions