shellcheck icon indicating copy to clipboard operation
shellcheck copied to clipboard

False positive for SC1003

Open austin987 opened this issue 8 years ago • 18 comments

For bugs

  • Rule Id (if any, e.g. SC1000): SC1003
  • My shellcheck version (shellcheck --version or "online"): 0.4.6 / online
  • [X] I tried on shellcheck.net and verified that this is still a problem on the latest commit

For new checks and feature suggestions

Here's a snippet or screenshot that shows the problem:


#!/bin/sh
echo hi | tr -d '\\'

Here's what shellcheck currently says:

echo hi | tr -d '\\'
                 ^-- SC1003: Want to escape a single quote? echo 'This is how it'''s done'.

Here's what I wanted or expected to see:

No warning. I only expect expect tr to delete the backslash (as it does) :)

austin987 avatar Mar 28 '17 00:03 austin987

Well, you tell it to delete anything that's a backslash or a backslash, which might warrant a different variation of escape warning, because it's not inconceivable that you meant to escape something.

^-- SCXXXX: It is redundant to repeat the same char in a tr list, and also redundant. See SCXXXX.

arth1 avatar Mar 29 '17 15:03 arth1

What's more, the example given in the shellcheck output is fatally wrong and will instantly break any script.

echo 'This is NOT how it'''s done'.

echo 'THIS is how it'\''s done'.

McDutchie avatar Mar 29 '17 23:03 McDutchie

@McDutchie : The incorrect ''' looks like a regression after 0.4.5 was released. Previous to rev 798, it reports:

^-- SC1003: Are you trying to escape that single quote? echo 'You'\''re doing it wrong'.

arth1 avatar Mar 30 '17 16:03 arth1

Ow, that's embarrassing. Not the easiest bug to spot in a code review:

parseProblemAt pos InfoC 1003 "Want to escape a single quote? echo 'This is how it'\''s done'.";

66c7cf1 doubles the escaping so the \ shows up properly.

koalaman avatar Apr 02 '17 05:04 koalaman

Many tools require that backslashes be doubled, so '\\' is perfectly valid and should not be flagged.

mjreed-wbd avatar Oct 19 '17 14:10 mjreed-wbd

I just ran into this. Here's a very cut down version of my script. I'm simply attempting to convert back slashes into forward slashes in a file path. I could use sed instead, but I'd prefer to understand this issue.

#!/bin/sh

echo 'test\path' | tr '\' '/'

Shellcheck outputs the message: ^-- SC1003: Want to escape a single quote? echo 'This is how it'\''s done'.

I've also tried '\\' and "\\". The former giving me the same message and the latter giving me a warning from tr saying: tr: warning: an unescaped backslash at end of string is not portable. What's the correct solution to this? Other than using a different tool to tr.

pd93 avatar Dec 14 '17 15:12 pd93

'\\' would be the correct way in terms of tr, but shellcheck incorrectly thinks you're trying to escape a '. You shouldn't let tooling bugs stop you from doing what's right though:

# shellcheck disable=SC1003 # No, I'm not escaping a '
echo 'test\path' | tr '\\' '/'

"\\\\" would make shellcheck be quiet about it, but it looks pretty awful.

koalaman avatar Dec 14 '17 17:12 koalaman

Or, one could use a private class: echo 'test\path' | tr '[=\\=]' '/'

... except that here, shellcheck seems to give wrong advice: ^-- SC2021: Don't use [] around classes in tr, it replaces literal square brackets.

In this case, the brackets are absolutely needed.

arth1 avatar Dec 14 '17 18:12 arth1

echo 'test\path' | tr '\[=\\=\]' '/'

seems to work and passes shellcheck for me:

austin@austin2:~$ cat -n test.sh ; shellcheck test.sh ; sh test.sh
     1	#!/bin/sh
     2	echo "Original"
     3	echo 'test\path' | tr '[=\\=]' '/'
     4	
     5	echo "New"
     6	echo 'test\path' | tr '\[=\\=\]' '/'

In test.sh line 3:
echo 'test\path' | tr '[=\\=]' '/'
                      ^-- SC2021: Don't use [] around classes in tr, it replaces literal square brackets.

Original
test/path
New
test/path

austin@austin2:~$ shellcheck --version
ShellCheck - shell script analysis tool
version: 0.4.6
license: GNU General Public License, version 3
website: http://www.shellcheck.net

austin@austin2:~$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

austin987 avatar Dec 14 '17 18:12 austin987

@austin987 thanks, echo 'test\path' | tr '\[=\\=\]' '/' worked perfectly for me

pd93 avatar Dec 15 '17 18:12 pd93

Many tools require that backslashes be doubled, so '\' is perfectly valid and should not be flagged.

I agree that this makes sense. While printf '\' and printf '\\' are the same, the latter could be used to silence shellcheck (and is probably more correct anyway).

blueyed avatar Jun 18 '18 05:06 blueyed

The warning for '[=\\=]' is a separate bug fixed in 75fb4da (thanks!). Adding escaping will cause [=] themselves to be replaced:

$ echo 'test][=path' | tr '\[=\\=\]' '/'
test///path

I would really suggest disabling it with a directive because '\\' is 100% correct and the programmer ultimately knows that better than ShellCheck, but if you really want a rewrite that doesn't trigger on the latest stable version, maybe:

echo 'test\path' | tr '\\x' '/x' 

for an arbitrary character x including x itself, a space or period or something.

koalaman avatar Jun 24 '18 00:06 koalaman

I've got another false positive:

sed -e '$a\' file_without_trailing_newline > file_with_trailing_newline
          ^-- SC1003: Want to escape a single quote? echo 'This is how it'\''s done'.

ljharb avatar Feb 04 '19 21:02 ljharb

I just use 'blah'\\ instead of 'blah\\'

Quasic avatar Feb 04 '19 22:02 Quasic

I've hit a false positive in this category -- defining IFS. Make a script with nothing more than this:

IFS=`\\`

...and shellcheck 0.6.0-107 will flag that with SC1003.

Example use in context:

IFS='\\' read -r -a array <<< "${VARIABLE}"

This example parses user input DOMAIN\username into an array.

terackspace avatar May 23 '19 20:05 terackspace

Got a false positive when using sed to replace '\'' with ' in a string:

printf '%s' "$s" | sed 's#'\''\\'\'''\''#'\''#g'
                               ^-- SC1003: Want to escape a single quote? echo 'This is how it'\''s done'.

rhenescu avatar Sep 29 '21 18:09 rhenescu

tr: warning: an unescaped backslash at end of string is not portable

solutions:

  • echo 'test\path' | tr '\\' '/'
  • echo 'test\path' | tr \\\\ /
  • echo 'test\path' | tr "\\\\" "/"
  • echo 'test\path' | tr '\[=\\=\]' '/'

milahu avatar Aug 13 '23 12:08 milahu

A way to at least circumvent this is to use double quotes instead of single quotes, but this is no real solution, right? Edit: Wait a second, now I'm getting tr: warning: an unescaped backslash at end of string is not portable, so this won't do, either.

arisboch avatar Apr 27 '24 11:04 arisboch