3

I am trying to parse some Autodesk Revit journal files, which have both comment lines that start with an apostrophe, and command lines that don't. The comment lines can further start with 'E or 'H or 'C to signify a time stamp which I need to work with as well. So I figured that my logic would be:

If Comment
  Switch TimeStampType
Else
  Command

I found this, and I figured if switch ($someString.ToLower()) works, then switch ($line.StartsWith()) would too (I know, that's a bit of a reach, as ToLower and StartsWith are completely different concepts).

However, this is throwing Cannot find an overload for "StartsWith" and the argument count: "0". at if ($line.StartsWith("'")). But that's a bit of a misdirect because if I REM the entire switch it throws no errors, so the error must be in the switch.

        if ($line.StartsWith("'")) {
            switch ($line.StartsWith()) {
                "'E " {
                    # handle Timestamp
                }
                "'H " {
                    # handle Timestamp
                }
                "'C " {
                    # handle Timestamp
                }
                Default {}
            }
        } else {
            if ($line -like "*$command*") {
                Write-Host "$line"
            }
        }

I have also tried escaping the apostrophes with `, with the same results, as well as using switch like this, as suggested in the link.

{$_ -eq "'E "} {
        # handle Timestamp
}

Again, with the same results. So finally I ended up with

    if ($line.StartsWith("'")) {
        switch ($line) {
            $_.StartsWith("'E ") {
                # handle Timestamp
            }
            $_.StartsWith("'H ") {
                # handle Timestamp
            }
            $_.StartsWith("'C ") {
                # handle Timestamp
            }
            Default {}
        }
    } else {
        if ($line -like "*$command*") {
            Write-Host "$line"
        }
    }

That works, but also seems perhaps inelegant. So, have I found the one or best answer, or is there a better approach here that I am missing?

Community
  • 1
  • 1
Gordon
  • 6,257
  • 6
  • 36
  • 89

2 Answers2

4

Instead of using String.StartsWith(), you could just use a wildcard switch:

switch -wildcard ($line){
  "'E *" {
    # $line starts with 'E
  }
  "'H *" {
    # $line starts with 'H
  }
  "'C *" {
    # $line starts with 'C
  }
}

or a regex switch:

switch -regex ($line){
  "^'E " {
    # $line starts with 'E
  }
  "^'H " {
    # $line starts with 'H
  }
  "^'C " {
    # $line starts with 'C
  }
}

Be aware that if you were to use "somestring".StartsWith() as your switch input argument, the only values you would ever catch would be $true or $false, since that's what StartsWith() returns:

switch($line.StartsWith("'E")){
  $true {
    # $line starts with 'E
  }
  $false {
    # $line doesn't start with 'E 
  }
}
user4003407
  • 21,204
  • 4
  • 50
  • 60
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • I think that Regex option is the most elegant. Usually I try to find a non regex approach, and only use Regex when there is no other (better) way to do it. In this case, seems like regex is best. – Gordon Jan 01 '17 at 18:54
  • If that's the case I would go for the wildcard one in this case – Mathias R. Jessen Jan 01 '17 at 18:58
1

You could also use the Substring method.

switch ($line.Substring(0,3)) {
    "'E " {
        # handle Timestamp
    }
    "'H " {
        # handle Timestamp
    }
    "'C " {
        # handle Timestamp
    }
    Default {}
}
Patrick Meinecke
  • 3,963
  • 2
  • 18
  • 26