none
match more than one arguement on a line RRS feed

  • Question

  • I read a file and I search some specific lines that contains the word "transfered" and the CODES "ZEN" and "ROK". My script should select only the lines with these three parameters BUT the ROK should not be a star character "*".

    Here an example and the condition that I wrote:

    lines:

    Transfered TWIST=1 ROK=TOTO ZEN=C2813310

    Transfered TEST2=3 ROK=* ZEN=C2813310

    Transfered CALIB=7 ROK=* ZEN=C2813310

    Transfered LIKR1=9 ROK=TOTO ZEN=C2813310

    My if condition in order to match the elements:

      $content = get-content "c:\test\log"

        foreach ($line in $content) {
            if ($line -match "Transfered.*ZEN=(.+?)\b.*")

    My question is how to add to the same "if" condition the "ROK" parameters that it should not be equal to a "*" star.

    So, at the end of the script, from the example above, I should have only these two lines where ROK is not equal to "*" :

    Transfered TWIST=1 ROK=TOTO ZEN=C2813310

    Transfered LIKR1=9 ROK=TOTO ZEN=C2813310

    My script does also other tasks but these tasks are based no this filter that I have to apply.

    Thank you in advance.

    ps: I tried this one but didn't work:

    if ($line -match "Transfered.*ZEN=(.+?).*ROK=(.+?)\b.*")

    Thursday, April 3, 2014 9:46 AM

Answers

  • Trying to match that in a single regular expression is awkward, if your attributes (ie, ZEN=, ROK=) aren't guaranteed to always be in the same order.  What I would probably do is write a function to take that line and turn it into a hashtable, then base your logic on that table.  This way, the order of the attributes on the line doesn't matter.  Something like this:

    function ConvertFrom-AttributeText
    {
        [CmdletBinding()]
        param (
            [Parameter(ValueFromPipeline = $true)]
            [string[]]
            $Line
        )
    
        process
        {
            if ($null -eq $Line) { return }
    
            foreach ($string in $line)
            {
                $reMatches = [regex]::Matches($string, '(\S+)\s*=\s*(\S+)')
    
                $hashTable = @{}
    
                foreach ($match in $reMatches)
                {
                    $hashTable[$match.Groups[1].Value] = $match.Groups[2].Value
                }
    
                $hashTable
            }
        }
    }
    
    $lines = 'Transfered TWIST=1 ROK=TOTO ZEN=C2813310',
             'Transfered TEST2=3 ROK=* ZEN=C2813310',
             'Transfered CALIB=7 ROK=* ZEN=C2813310',
             'Transfered LIKR1=9 ROK=TOTO ZEN=C2813310'
    
    $lines -match 'Transfered' |
    ConvertFrom-AttributeText |
    Where-Object { $_['ZEN'] -and $_['ROK'] -ne '*' } |
    ForEach-Object {
        # Do something with $_ (which is a hashtable guaranteed to have a value for $_['ZEN']
    }
    

    • Marked as answer by kouzoulos Thursday, April 3, 2014 2:54 PM
    Thursday, April 3, 2014 2:12 PM

All replies

  • Trying to match that in a single regular expression is awkward, if your attributes (ie, ZEN=, ROK=) aren't guaranteed to always be in the same order.  What I would probably do is write a function to take that line and turn it into a hashtable, then base your logic on that table.  This way, the order of the attributes on the line doesn't matter.  Something like this:

    function ConvertFrom-AttributeText
    {
        [CmdletBinding()]
        param (
            [Parameter(ValueFromPipeline = $true)]
            [string[]]
            $Line
        )
    
        process
        {
            if ($null -eq $Line) { return }
    
            foreach ($string in $line)
            {
                $reMatches = [regex]::Matches($string, '(\S+)\s*=\s*(\S+)')
    
                $hashTable = @{}
    
                foreach ($match in $reMatches)
                {
                    $hashTable[$match.Groups[1].Value] = $match.Groups[2].Value
                }
    
                $hashTable
            }
        }
    }
    
    $lines = 'Transfered TWIST=1 ROK=TOTO ZEN=C2813310',
             'Transfered TEST2=3 ROK=* ZEN=C2813310',
             'Transfered CALIB=7 ROK=* ZEN=C2813310',
             'Transfered LIKR1=9 ROK=TOTO ZEN=C2813310'
    
    $lines -match 'Transfered' |
    ConvertFrom-AttributeText |
    Where-Object { $_['ZEN'] -and $_['ROK'] -ne '*' } |
    ForEach-Object {
        # Do something with $_ (which is a hashtable guaranteed to have a value for $_['ZEN']
    }
    

    • Marked as answer by kouzoulos Thursday, April 3, 2014 2:54 PM
    Thursday, April 3, 2014 2:12 PM
  • Thank you David for this solution.
    Thursday, April 3, 2014 2:54 PM