Last active
August 29, 2015 14:02
-
-
Save acken/5825b4cf2c755b27f818 to your computer and use it in GitHub Desktop.
Command string parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Takes a "quoted argument string ignoring \" escaped" arguments. Returns an array of arguments | |
let commandStringToArguments (cmd: string) = | |
// Checks whether a quote is lead by an escape char | |
let isUnescapedQuote (i, c) = | |
c.Equals('"') && (i.Equals(0) || (cmd |> Seq.toArray).[i-1] <> '\\') | |
// Get the start and end position of quoted strings | |
let quotedStrings = | |
cmd | |
|> Seq.toArray | |
|> Array.mapi (fun i c -> (i, c)) | |
|> Array.filter (fun point -> isUnescapedQuote point) | |
|> Array.map (fun (i, c) -> i) | |
|> Seq.pairwise | |
|> Seq.toArray | |
|> Array.map (fun (s, e) -> (s+1, e-1)) | |
// Checks if current position is inside a quoted string | |
let outsideQuotedString i = | |
let count = | |
quotedStrings | |
|> Array.filter (fun (sstart, send) -> i >= sstart && i <= send) | |
|> Array.length | |
count.Equals(0) | |
// Locate all unquoted words | |
let words = | |
cmd | |
|> Seq.toArray | |
|> Array.mapi (fun i c -> (i+1, c)) | |
|> Array.filter (fun (i, c) -> c.Equals(' ')) | |
|> Array.map (fun (i, c) -> i) | |
|> Array.filter (fun i -> outsideQuotedString i) | |
|> Array.append [|0|] | |
// Get start positions for all commands in command string | |
let startPositions = | |
words | |
|> Array.append (quotedStrings |> Array.map (fun (start, _) -> start)) | |
|> Array.sort | |
|> Seq.distinct | |
|> Seq.toArray | |
// Parse out a list of commands from start and end position | |
startPositions | |
|> Array.mapi (fun i p -> | |
if i.Equals((startPositions |> Array.length)-1) then (p, cmd.Length) | |
else (p, startPositions.[i+1]-1)) | |
|> Array.map (fun (s, e) -> cmd.Substring(s, e-s)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment