# here-doc -- swallow it to avoid false hits within its body (but keep the
# command to which it was attached)
-/<<[ ]*[-\\']*[A-Za-z0-9_]/ {
- s/^\(.*\)<<[ ]*[-\\']*\([A-Za-z0-9_][A-Za-z0-9_]*\)'*/<\2>\1<</
+/<<[ ]*[-\\'"]*[A-Za-z0-9_]/ {
+ s/^\(.*\)<<[ ]*[-\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</
s/[ ]*<<//
:hereslurp
N
:slurp
# incomplete line "...\"
/\\$/bincomplete
-# multi-line quoted string "...\n..."
-/^[^"]*"[^"]*$/bdqstring
-# multi-line quoted string '...\n...' (but not contraction in string "it's so")
-/^[^']*'[^']*$/{
+# multi-line quoted string "...\n..."?
+/"/bdqstring
+# multi-line quoted string '...\n...'? (but not contraction in string "it's")
+/'/{
/"[^'"]*'[^'"]*"/!bsqstring
}
+:folded
# here-doc -- swallow it
-/<<[ ]*[-\\']*[A-Za-z0-9_]/bheredoc
+/<<[ ]*[-\\'"]*[A-Za-z0-9_]/bheredoc
# comment or empty line -- discard since final non-comment, non-empty line
# before closing ")", "done", "elsif", "else", or "fi" will need to be
# re-visited to drop "suspect" marking since final line of those constructs
# "$(...)" -- command substitution; not closing ")"
/\$([^)][^)]*)[^)]*$/bcheckchain
# multi-line "$(...\n...)" -- command substitution; treat as nested subshell
-/\$([ ]*$/bnest
+/\$([^)]*$/bnest
# "=(...)" -- Bash array assignment; not closing ")"
/=(/bcheckchain
# closing "...) &&"
s/\\\n//
bslurp
-# found multi-line double-quoted string "...\n..." -- slurp until end of string
+# check for multi-line double-quoted string "...\n..." -- fold to one line
:dqstring
-s/"//g
+# remove all quote pairs
+s/"\([^"]*\)"/@!\1@!/g
+# done if no dangling quote
+/"/!bdqdone
+# otherwise, slurp next line and try again
N
s/\n//
-/"/!bdqstring
-bcheckchain
+bdqstring
+:dqdone
+s/@!/"/g
+bfolded
-# found multi-line single-quoted string '...\n...' -- slurp until end of string
+# check for multi-line single-quoted string '...\n...' -- fold to one line
:sqstring
-s/'//g
+# remove all quote pairs
+s/'\([^']*\)'/@!\1@!/g
+# done if no dangling quote
+/'/!bsqdone
+# otherwise, slurp next line and try again
N
s/\n//
-/'/!bsqstring
-bcheckchain
+bsqstring
+:sqdone
+s/@!/'/g
+bfolded
# found here-doc -- swallow it to avoid false hits within its body (but keep
# the command to which it was attached)
:heredoc
-s/^\(.*\)<<[ ]*[-\\']*\([A-Za-z0-9_][A-Za-z0-9_]*\)'*/<\2>\1<</
+s/^\(.*\)<<[ ]*[-\\'"]*\([A-Za-z0-9_][A-Za-z0-9_]*\)['"]*/<\2>\1<</
s/[ ]*<<//
:hereslurpsub
N
}
s/^<[^>]*>//
s/\n.*$//
-bcheckchain
+bfolded
# found "case ... in" -- pass through untouched
:case