Skip to content

Shell escaping issues #158

@mjk-gh

Description

@mjk-gh

Using https://www.shellcheck.net/ to check for githooks' POSIX compliance (inspired by #157), shellcheck spat out a few warnings regarding backslashes in double-quoted strings for version 2103.272039-8ab988:


In githooks line 160:
            SHARED_LOCAL_REPOS_LIST=$(grep -E "^[^#\n\r ].*$" <"$(pwd)/.githooks/.shared")
                                                   ^-- SC1117: Backslash is literal in "\n". Prefer explicit escaping: "\\n".
                                                     ^-- SC1117: Backslash is literal in "\r". Prefer explicit escaping: "\\r".


In githooks line 602:
            SHARED_REPOS_LIST=$(grep -E "^[^#\n\r ].*$" <"$(pwd)/.githooks/.shared")
                                             ^-- SC1117: Backslash is literal in "\n". Prefer explicit escaping: "\\n".
                                               ^-- SC1117: Backslash is literal in "\r". Prefer explicit escaping: "\\r".


In githooks line 910:
    if echo "$1" | grep -qE "\-\-(shared|local|global)"; then
                             ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".
                               ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".


In githooks line 977:
    if echo "$1" | grep -qE "\-\-(shared|local|global)"; then
                             ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".
                               ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".


In githooks line 1034:
            if echo "$LINE" | grep -qE "^[^#\n\r ].*$"; then
                                            ^-- SC1117: Backslash is literal in "\n". Prefer explicit escaping: "\\n".
                                              ^-- SC1117: Backslash is literal in "\r". Prefer explicit escaping: "\\r".


In githooks line 1213:
            SHARED_REPOS_LIST=$(grep -E "^[^#\n\r ].*$" <"$(pwd)/.githooks/.shared")
                                             ^-- SC1117: Backslash is literal in "\n". Prefer explicit escaping: "\\n".
                                               ^-- SC1117: Backslash is literal in "\r". Prefer explicit escaping: "\\r".


In githooks line 1267:
        SHARED_HOOKS=$(grep -E "^[^#\n\r ].*$" <"$(pwd)/.githooks/.shared")
                                    ^-- SC1117: Backslash is literal in "\n". Prefer explicit escaping: "\\n".
                                      ^-- SC1117: Backslash is literal in "\r". Prefer explicit escaping: "\\r".


In githooks line 1305:
    if echo "$1" | grep -iEq "^\s*file://"; then
                               ^-- SC1117: Backslash is literal in "\s". Prefer explicit escaping: "\\s".


In githooks line 2336:
        if echo "$2" | grep -qE "\-\-(local)"; then
                                 ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".
                                   ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".


In githooks line 2347:
        if echo "$2" | grep -qE "\-\-(local)"; then
                                 ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".
                                   ^-- SC1117: Backslash is literal in "\-". Prefer explicit escaping: "\\-".


I just tested for the first error:

$ cat << EOF > unix
# This is a comment

once
upon
a
time

there
was
an empty
line
EOF
$ cp unix dos
$ unix2dos dos
$ posh   # optional, result is the same with bash
$ grep -E "^[^#\n\r ].*$" < unix
once
upon
a
time
there
was
an empty
line
$ grep -E "^[^#\n\r ].*$" < dos

once
upon
a
time

there
was
an empty
line
$

Seems legit. :-} Normal grep cannot match occurrences of '\n' anyway (except '$' for the end of the line), only with "--perl-regexp", but I doubt that this is POSIX compliant.

For above grep expressions in lines

  • 160
  • 602
  • 1034
  • 1213
  • 1267

a working portable/POSIX construct would be:

cat $FILE | tr -d '\r' | grep -v '^\(#\|$\)' 

(mind the single quotes!) or for UUoC award fappers:

tr -d '\r' < FILE | grep -v '^\(#\|$\)' 

(mind the single quotes!)

Or with "-E" to forgo the backslashes, just don't know how portable that option is.

If the OCD part in you gets annoyed by shellcheck's warnings for expressions linke

grep -qE "\-\-(shared|local|global)"

in lines

  • 906
  • 977
  • 2336
  • 2347

(which are technically correct, but useless, as shellcheck doesn't get the semantics),
I would instead use

grep -qE '[-]-(shared|local|global)'

or just use the original expressions, but in single quotes.

Use of "stop option processing"-option -- would have been ideal, but is most likely not portable.

In general, I would use single quotes (´) instead of double quotes (") for anything other than pure [A-Z0-9_ ], except if I am sure that I want the shell to process characters with special meaning, like dollar ($), backtick (`), or backslash (\).

P.S.: Sorry for the humongous amount of text for such a teensy issue, I got carried away. :-}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions