diff --git a/ini_test.go b/ini_test.go
index 306a2a8..aaad1a0 100644
--- a/ini_test.go
+++ b/ini_test.go
@@ -567,6 +567,31 @@ key = test value more text
assert.Equal(t, `test value more text`, f.Section("").Key("key").String())
})
+ t.Run("unescape double quotes with backslash continuation", func(t *testing.T) {
+ f, err := LoadSources(LoadOptions{
+ UnescapeValueDoubleQuotes: true,
+ }, []byte(`hello = "!f() { \
+ echo "hello world"; \
+};f"`))
+ require.NoError(t, err)
+ require.NotNil(t, f)
+
+ expected := `!f() { \
+ echo "hello world"; \
+};f`
+ assert.Equal(t, expected, f.Section("").Key("hello").String())
+
+ t.Run("inverse case", func(t *testing.T) {
+ _, err := LoadSources(LoadOptions{
+ UnescapeValueDoubleQuotes: true,
+ IgnoreContinuation: true,
+ }, []byte(`hello = "!f() { \
+ echo "hello world"; \
+};f"`))
+ require.Error(t, err)
+ })
+ })
+
t.Run("can parse small python-compatible INI files", func(t *testing.T) {
f, err := LoadSources(LoadOptions{
AllowPythonMultilineValues: true,
diff --git a/parser.go b/parser.go
index 44fc526..909d633 100644
--- a/parser.go
+++ b/parser.go
@@ -181,6 +181,13 @@ func (p *parser) readMultilines(line, val, valQuote string) (string, error) {
pos := strings.LastIndex(next, valQuote)
if pos > -1 {
+ // Check if the line ends with backslash continuation after the quote
+ restOfLine := strings.TrimRight(next[pos+len(valQuote):], "\r\n")
+ if !p.options.IgnoreContinuation && strings.HasSuffix(strings.TrimSpace(restOfLine), "\\") {
+ val += next
+ continue
+ }
+
val += next[:pos]
comment, has := cleanComment([]byte(next[pos:]))