我有一个包含以下内容的文本文件,我需要检索分配给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
)
在这一点上,我不知道该如何获取所需的价值。我认为可以使用的选项有:
如何获取该值,如果该值不存在则失败?
答案 0 :(得分:1)
我认为所有选项都是合理的-这取决于文件的实际复杂程度。如果没有转义,那么您可能只需要在行中寻找=
,并使用它来将行拆分为键值对。如果语法更复杂,则可能并非总是如此。
我的首选方法是在字符串上使用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)
活动模式技巧很巧妙,但是如果您只需要一个地方,可能会不必要地使代码复杂化。