• Error msg from shellcheck

    From Kenny McCormack@21:1/5 to All on Wed Jun 28 11:19:59 2023
    I ran shellcheck on one of my bash scripts and got the output shown below:

    *) printf "\a"
    ^-- SC1117: Backslash is literal in "\a". Prefer explicit escaping: "\\a".
    This happens for every instance like this - where I have something like \a
    or \n or \r or whatever in a string for things like echo or printf.

    This surprises me, b/c the above is perfectly standard and normal. And
    works perfectly well, so there clearly is nothing to change or fix here.

    In fact, I'd expect something like:

    printf "\\a"

    to print a literal backslash followed by a literal a. This doesn't happen, which also surprises ms.

    Can someone explain what is going on here and why shellcheck complains?
    (Yes, I know shellcheck complains about lots of stuff - most of it bogus -
    but this one I find curious...)

    --
    The key difference between faith and science is that in science, evidence that doesn't fit the theory tends to weaken the theory (that is, make it less likely to
    be believed), whereas in faith, contrary evidence just makes faith stronger (on the assumption that Satan is testing you - trying to make you abandon your faith).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to [email protected] on Wed Jun 28 13:01:48 2023
    In article <[email protected]>,
    Richard Kettlewell <[email protected]d> wrote:
    ...
    In shell, the string literal "\a" means the two character string 0x5C
    0x61, i.e. a backslash followed by lower-case a.

    $ echo "\a" | hd
    00000000 5c 61 0a |\a.|
    00000003

    I guess you expected it to mean 0x07? If so then the mismatch between >expectation and reality seems like justification for the shellcheck
    warning.

    No, quite the opposite - in terms of what *I* expect. I know shell syntax
    as well as (just about) anyone here, and I'm fully aware that the shell
    doesn't translate/interpret backslash sequences (unless you ask nicely for
    it to do so with something like $'\n').

    Maybe the author(s) of shellcheck think that *some* users might expect that.

    In fact, I'd expect something like:

    printf "\\a"

    to print a literal backslash followed by a literal a. This doesn't happen, >> which also surprises ms.

    I don't know if I'd have predicted it cold, but it's consistent with
    the documentation for printf(1).

    According to Geoff, passing \\a is exactly the same as passing \a.
    (So, there's that...)

    --
    You know politics has really been turned upside down when you have someone in the
    government with a last name of Cheney (Liz, Senator from Wyoming) who is the voice of
    reason.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Kettlewell@21:1/5 to Kenny McCormack on Wed Jun 28 13:27:37 2023
    [email protected] (Kenny McCormack) writes:
    I ran shellcheck on one of my bash scripts and got the output shown below:

    *) printf "\a"
    ^-- SC1117: Backslash is literal in "\a". Prefer explicit escaping: "\\a".
    This happens for every instance like this - where I have something like \a
    or \n or \r or whatever in a string for things like echo or printf.

    This surprises me, b/c the above is perfectly standard and normal. And
    works perfectly well, so there clearly is nothing to change or fix here.

    In shell, the string literal "\a" means the two character string 0x5C
    0x61, i.e. a backslash followed by lower-case ‘a’.

    $ echo "\a" | hd
    00000000 5c 61 0a |\a.|
    00000003

    I guess you expected it to mean 0x07? If so then the mismatch between expectation and reality seems like justification for the shellcheck
    warning.

    In fact, I'd expect something like:

    printf "\\a"

    to print a literal backslash followed by a literal a. This doesn't happen, which also surprises ms.

    I don’t know if I’d have predicted it “cold”, but it’s consistent with
    the documentation for printf(1).

    --
    https://www.greenend.org.uk/rjk/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Geoff Clare@21:1/5 to Kenny McCormack on Wed Jun 28 13:36:56 2023
    Kenny McCormack wrote:

    I ran shellcheck on one of my bash scripts and got the output shown below:

    *) printf "\a"
    ^-- SC1117: Backslash is literal in "\a". Prefer explicit escaping: "\\a".
    This happens for every instance like this - where I have something like \a
    or \n or \r or whatever in a string for things like echo or printf.

    This surprises me, b/c the above is perfectly standard and normal. And
    works perfectly well, so there clearly is nothing to change or fix here.

    In fact, I'd expect something like:

    printf "\\a"

    to print a literal backslash followed by a literal a. This doesn't happen, which also surprises ms.

    Can someone explain what is going on here and why shellcheck complains?
    (Yes, I know shellcheck complains about lots of stuff - most of it bogus - but this one I find curious...)

    According to POSIX, a backslash inside double-quotes escapes the following:

    $ ` " \ <newline>

    If it isn't followed by one of those, it is treated as a literal backslash.

    So in:

    printf "\\a"

    the first \ escapes the second and printf is passed \a

    whereas in:

    printf "\a"

    the \ is treated as literal and printf is passed \a

    --
    Geoff Clare <[email protected]>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to [email protected] on Wed Jun 28 12:56:00 2023
    In article <[email protected]>,
    Geoff Clare <[email protected]> wrote:
    ...
    According to POSIX, a backslash inside double-quotes escapes the following:

    $ ` " \ <newline>

    If it isn't followed by one of those, it is treated as a literal backslash.

    So in:

    printf "\\a"

    the first \ escapes the second and printf is passed \a

    whereas in:

    printf "\a"

    the \ is treated as literal and printf is passed \a

    Exactly. So, you're saying that the two are exactly equivalent - the underlying command (printf in this case) sees the exact same thing in both cases.

    So, the question is: Why does shellcheck complain?
    That's the point of my starting this thread.

    (Yes, I know that shellcheck can complain about anything it wants to and
    that it often complains about things that are perfectly OK. But I wanted
    to start a discussion about shellcheck itself - which is/would be on-topic
    in this newsgroup, since it (shellcheck) is often recommended here. In a
    way, my overall point is: Don't take shellcheck too seriously...)

    --
    Kenny, I'll ask you to stop using quotes of mine as taglines.

    - Rick C Hodgin -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Kenny McCormack on Wed Jun 28 15:19:20 2023
    On 28.06.2023 14:56, Kenny McCormack wrote:

    So, the question is: Why does shellcheck complain?
    That's the point of my starting this thread.

    I don't know anything about the "quality" of that tool.
    But didn't you answer that question already in your OP...?

    (Yes, I know shellcheck complains about lots of stuff -
    most of it bogus - but this one I find curious...)

    I mean; the semantics are obviously clear, so if you care
    about that 'spellcheck' tool you could send a bug-report.
    OTOH, the tool says:
    _Prefer_ explicit escaping: "\\a".
    which rather sounds like a style suggestion.

    Janis

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Kenny McCormack on Wed Jun 28 15:08:39 2023
    [email protected] (Kenny McCormack) writes:

    I ran shellcheck on one of my bash scripts and got the output shown below:

    *) printf "\a"
    ^-- SC1117: Backslash is literal in "\a". Prefer explicit escaping: "\\a".
    This happens for every instance like this - where I have something like \a
    or \n or \r or whatever in a string for things like echo or printf.

    This surprises me, b/c the above is perfectly standard and normal. And
    works perfectly well, so there clearly is nothing to change or fix here.

    In fact, I'd expect something like:

    printf "\\a"

    to print a literal backslash followed by a literal a. This doesn't happen, which also surprises ms.

    This has now been explained.

    Can someone explain what is going on here and why shellcheck
    complains?

    Note that it's only saying "prefer". As you are now aware, there's
    nothing wrong with "\a" and it means the same as "\\n" but I imagine
    that shellcheck is suggesting being explicit. You were a bit surprised
    that "\\a" has the same effect, but it had you been in the habit of
    explcitily quoting all backslashes I don't think you would have been.
    It makes it absolutely clear that printf gets a backslash and an 'a' and
    that it is printf the decides what to do with that sequence.

    There's also the (tiny) possibility that a new shell might choose to
    give "\a" a meaning thereby altering existing script where a change to
    the meaning of "\\a" would be unimaginable.

    TL;TD: keep everything as unambiguous as possible.

    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Kettlewell@21:1/5 to Kenny McCormack on Wed Jun 28 16:44:50 2023
    [email protected] (Kenny McCormack) writes:
    Richard Kettlewell <[email protected]d> wrote:
    ...
    In shell, the string literal "\a" means the two character string 0x5C
    0x61, i.e. a backslash followed by lower-case a.

    $ echo "\a" | hd
    00000000 5c 61 0a |\a.|
    00000003

    I guess you expected it to mean 0x07? If so then the mismatch between >>expectation and reality seems like justification for the shellcheck >>warning.

    No, quite the opposite - in terms of what *I* expect. I know shell syntax
    as well as (just about) anyone here, and I'm fully aware that the shell doesn't translate/interpret backslash sequences (unless you ask nicely for
    it to do so with something like $'\n').

    The original post was consistent both with you knowing exactly what was
    going on, but also with having two misapprehensions that cancelled each
    other out. Since you said you mis-predicted the behavior of the second
    printf command, the seccond interpretation is the one I arrived at.

    Maybe the author(s) of shellcheck think that *some* users might expect that.

    It’s a reasonable thing to think. For instance anyone more familiar with
    C than shell would expect it.

    --
    https://www.greenend.org.uk/rjk/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to [email protected] on Wed Jun 28 17:41:38 2023
    In article <[email protected]>,
    Richard Kettlewell <[email protected]d> wrote:
    ...
    Its a reasonable thing to think. For instance anyone more familiar with
    C than shell would expect it.

    Well, as I've tried to make clear, it (this thread) is not about me.

    It's about shellcheck - and why they made it work the way they did.

    And about whether it is a good thing to recommend to the newbies...

    --
    There are many self-professed Christians who seem to think that because
    they believe in Jesus' sacrifice they can reject Jesus' teachings about
    how we should treat others. In this country, they show that they reject
    Jesus' teachings by voting for Republicans.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From William Ahern@21:1/5 to Kenny McCormack on Thu Jun 29 16:21:45 2023
    Kenny McCormack <[email protected]> wrote:
    In article <[email protected]>,
    Geoff Clare <[email protected]> wrote:
    ...
    According to POSIX, a backslash inside double-quotes escapes the following: >>
    $ ` " \ <newline>

    If it isn't followed by one of those, it is treated as a literal backslash. >>
    So in:

    printf "\\a"

    the first \ escapes the second and printf is passed \a

    whereas in:

    printf "\a"

    the \ is treated as literal and printf is passed \a

    Exactly. So, you're saying that the two are exactly equivalent - the underlying command (printf in this case) sees the exact same thing in both cases.

    So, the question is: Why does shellcheck complain?
    That's the point of my starting this thread.

    In some other environments where backslash or backslash-style (e.g. %)
    escaping is used, including in other shell contexts, an undefined escape sequence results in a) an error, b) the sequence elided in its entirety, or
    c) the sequence treated as an equivalent long form for the ordinary
    character. Or even some combination, whether deliberate or accidental, especially when you consider trailing or truncated sequences (e.g. lone backslash at the end of a string). For the printf utility, undefined
    backslash sequences produce unspecified behavior; for \y Bash produces '\y' whereas OpenBSD sh produces a diagnostic and 'y'.

    Notably, POSIX shell specifies option 'c' for sequences outside quotes,

    2.2.1 Escape Character (Backslash)
    A <backslash> that is not quoted shall preserve the literal value of the
    following character, with the exception of a <newline>.

    which is nearly the opposite of the behavior within double-quotes.

    Less notable, but you also get option 'c' behavior within bracket
    expressions of regular expressions and shell pattern matching notation. IME, across various environments option 'c' seems the most common, perhaps
    because it's closest to DWIM--don't treat the subsequent character as
    special, regardless of whether it would otherwise have been treated differently. For example, in JSON an undefined sequence is illegal, but in practice most libraries implement option 'c', perhaps because that's what ECMAScript explicitly specifies[1] for string literals; and Perl both
    in strings and regular expressions: "y" =~ /^\y$/ && "\y" =~ /^y$/ or die.

    Given the varying treatment of strings in the shell is something of an
    enigma to most programmers, arguably even most who regularly write shell
    code, that shellcheck diagnostic seems easier to defend than most.

    [1] https://262.ecma-international.org/14.0/#prod-CharacterEscapeSequence

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Kenny McCormack on Fri Jun 30 00:36:39 2023
    On 2023-06-28, Kenny McCormack <[email protected]> wrote:
    In article <[email protected]>,
    Geoff Clare <[email protected]> wrote:
    ...
    According to POSIX, a backslash inside double-quotes escapes the following: >>
    $ ` " \ <newline>

    If it isn't followed by one of those, it is treated as a literal backslash. >>
    So in:

    printf "\\a"

    the first \ escapes the second and printf is passed \a

    whereas in:

    printf "\a"

    the \ is treated as literal and printf is passed \a

    Exactly. So, you're saying that the two are exactly equivalent - the underlying command (printf in this case) sees the exact same thing in both cases.

    So, the question is: Why does shellcheck complain?

    It's a useless nuisance diagnostic which encourages an undesirable
    coding practice. POSIX clearly states, that inside double quotes:

    The <backslash> shall retain its special meaning as an escape character
    (see Escape Character (Backslash)) only when followed by one of the
    following characters when considered special:

    $ ` " \ <newline>


    Inside double quotes, \a means \a and that's it. Users of printf
    depend on this and do not write \\a, which is unidiomatic, and
    breaks the deliberate similarity to the C printf.

    It should not be diagnosed. Instead, the reverse should be diagnosed!
    Whenever a double backslash appears where the second backslash is not immediately followed by one of the above five characters, shellcheck
    should warn about a useless use of backslash escape.

    This is not a UUOBE: "\\$". It encodes the text \$.

    This is a UUOBE: "\\a", equivalent to "\a".

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)