forked from direnv/go-dotenv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
93 lines (78 loc) · 2.27 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Package dotenv implements the parsing of the .env format.
//
// There is no formal definition of the format but it has been introduced by
// https://github.com/bkeepers/dotenv which is thus canonical.
package dotenv
import (
"regexp"
"strings"
)
// LINE is the regexp matching a single line
const LINE = `
\A
\s*
(?:export\s+)? # optional export
([\w\.]+) # key
(?:\s*=\s*|:\s+?) # separator
( # optional value begin
'(?:\'|[^'])*' # single quoted value
| # or
"(?:\"|[^"])*" # double quoted value
| # or
[^#\n]+ # unquoted value
)? # value end
\s*
(?:\#.*)? # optional comment
\z
`
var linesRe = regexp.MustCompile("[\\r\\n]+")
var lineRe = regexp.MustCompile(
regexp.MustCompile("\\s+").ReplaceAllLiteralString(
regexp.MustCompile("\\s+# .*").ReplaceAllLiteralString(LINE, ""), ""))
// Parse reads a string in the .env format and returns a map of the extracted key=values.
//
// Ported from https://github.com/bkeepers/dotenv/blob/84f33f48107c492c3a99bd41c1059e7b4c1bb67a/lib/dotenv/parser.rb
func Parse(data string) (map[string]string, error) {
var dotenv = make(map[string]string)
for _, line := range linesRe.Split(data, -1) {
match := lineRe.FindStringSubmatch(line)
// commented line or invalid line
// TODO: return error if invalid
if len(match) == 0 {
continue
}
key := match[1]
value := parseValue(match[2])
dotenv[key] = value
}
return dotenv, nil
}
// MustParse works the same as Parse but panics on error
func MustParse(data string) map[string]string {
env, err := Parse(data)
if err != nil {
panic(err)
}
return env
}
func parseValue(value string) string {
if len(value) > 1 {
if value[0:1] == "'" && value[len(value)-1:] == "'" {
value = value[1 : len(value)-1]
} else if value[0:1] == `"` && value[len(value)-1:] == `"` {
value = value[1 : len(value)-1]
value = expandNewLines(value)
value = unescapeCharacters(value)
}
}
return value
}
var escRe = regexp.MustCompile("\\\\([^$])")
func unescapeCharacters(value string) string {
return escRe.ReplaceAllString(value, "$1")
}
func expandNewLines(value string) string {
value = strings.Replace(value, "\\n", "\n", -1)
value = strings.Replace(value, "\\r", "\r", -1)
return value
}