Чтение текстового файла, итерация по строкам для поиска совпадения и возврат значения с помощью FSharp - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть текстовый файл, который содержит следующее, и мне нужно получить значение, присвоенное taskId, которое в данном случае равно AWc34YBAp0N7ZCmVka2u .

projectKey=ProjectName
serverUrl=http://localhost:9090
serverVersion=10.5.32.3
strong text**interfaceUrl=http://localhost:9090/interface?id=ProjectName
taskId=AWc34YBAp0N7ZCmVka2u
taskUrl=http://localhost:9090/api/ce/task?id=AWc34YBAp0N7ZCmVka2u

У меня есть два разных способачтения файла, который я написал.

let readLines (filePath:string) = seq {
 use sr = new StreamReader (filePath)
 while not sr.EndOfStream do
     yield sr.ReadLine ()
}

readLines (FindFile currentDirectory "../**/sample.txt")
|> Seq.iter (fun line -> 
   printfn "%s" line
)

и

let readLines (filePath:string) = 
  (File.ReadAllLines filePath)

readLines (FindFile currentDirectory "../**/sample.txt")
|> Seq.iter (fun line -> 
   printfn "%s" line
)

На данный момент я не знаю, как приблизиться к получению нужного мне значения.Опции, которые, я думаю, находятся на столе:

  • use Contains ()
  • Regex
  • Тип записи
  • Активный шаблон

Как я могу вернуть это значение, если оно не существует?

1 Ответ

0 голосов
/ 27 ноября 2018

Я думаю, что все варианты будут разумными - это зависит от того, насколько сложным будет файл.Если экранирования нет, вы, вероятно, можете просто найти = в строке и использовать его, чтобы разбить строку на пару ключ-значение.Если синтаксис более сложный, это может не всегда работать.

Мой предпочтительный метод - использовать Split в строке - тогда вы можете filter найти значения с требуемым ключом, mapчтобы получить значение и использовать Seq.head, чтобы получить значение:

["foo=bar"]
|> Seq.map (fun line -> line.Split('='))
|> Seq.filter (fun kvp -> kvp.[0] = "foo")
|> Seq.map (fun kvp -> kvp.[1])
|> Seq.head

Используя активные шаблоны, вы можете определить шаблон, который принимает строку и разбивает ее, используя = в список:

let (|Split|) (s:string) = s.Split('=') |> List.ofSeq

Затем можно получить значение, используя Seq.pick с сопоставлением с шаблоном, который ищет строки, в которых подстрока до = равна, например, foo:

["foo=bar"] |> Seq.pick (function
  | Split ["foo"; value] -> Some value
  | _ -> None)

Активный шаблонхитрость довольно изящна, но это может излишне усложнить код, если вам нужно только это в одном месте.

...