shellcheck
shellcheck copied to clipboard
False positive for SC1003
For bugs
- Rule Id (if any, e.g. SC1000): SC1003
- My shellcheck version (
shellcheck --versionor "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) :)
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.
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 : 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'.
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.
Many tools require that backslashes be doubled, so '\\' is perfectly valid and should not be flagged.
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.
'\\' 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.
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.
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 thanks, echo 'test\path' | tr '\[=\\=\]' '/' worked perfectly for me
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).
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.
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'.
I just use 'blah'\\ instead of 'blah\\'
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.
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'.
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 '\[=\\=\]' '/'
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.