读取文本文件,遍历行以找到匹配项,并使用 FSharp return 值
Reading text file, iterating over lines to find a match, and return the value with FSharp
我有一个包含以下内容的文本文件,我需要检索分配给 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
)
在这一点上,我不知道如何获得我需要的价值。我认为 table 上的选项是:
- 使用 Contains()
- 正则表达式
- 记录类型
- 活动模式
如果这个值不存在,我如何返回并失败?
我认为所有选项都是合理的 - 这取决于文件的实际复杂程度。如果没有转义,那么您可能只需要在行中查找 =
并使用它将行拆分为键值对。如果语法更复杂,这可能并不总是有效。
我的首选方法是在字符串上使用 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)
活动模式技巧非常简洁,但如果您只在一个地方需要它,它可能会使代码不必要地复杂化。
我有一个包含以下内容的文本文件,我需要检索分配给 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
)
在这一点上,我不知道如何获得我需要的价值。我认为 table 上的选项是:
- 使用 Contains()
- 正则表达式
- 记录类型
- 活动模式
如果这个值不存在,我如何返回并失败?
我认为所有选项都是合理的 - 这取决于文件的实际复杂程度。如果没有转义,那么您可能只需要在行中查找 =
并使用它将行拆分为键值对。如果语法更复杂,这可能并不总是有效。
我的首选方法是在字符串上使用 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)
活动模式技巧非常简洁,但如果您只在一个地方需要它,它可能会使代码不必要地复杂化。