shellcheck --version or "online"): 0.7.0#!/bin/sh
# shell is dash
echo "0123456789ABCDEF" | sed s/[^0-9]/\ /g
echo "0123456789ABCDEF" | sed 's/[^0-9]/\ /g'
In ./sc-test.sh line 3:
echo "0123456789ABCDEF" | sed s/[^0-9]/\ /g
^----^ SC2039: In POSIX sh, ^ in place of ! in glob bracket expressions is undefined.
I do not understand why the quoted sed script does not trigger the same warning.
Because the meta-characters lose their special meanings if they are quoted.
The meta-characters are β!β, β*β, β?β, and β[β in dash. A left bracket (β[β) introduces a character class. The character class may be complemented by making an exclamation point ("!") the first character of the character class.
In bash you can use "^" in place of "!" to complement the character class.
See "Shell Patterns" section at https://www.man7.org/linux/man-pages/man1/dash.1.html and "Pattern Matching" section at https://www.man7.org/linux/man-pages/man1/bash.1.html for reference documentation.
Keep in mind that, if no matching filenames are found, and the shell option nullglob is not enabled, the word is left unchanged.
That is why unquoted s/[^0-9]/\ /g often works: because no matching filenames are found.
In bash you can use "^" in place of "!" to complement the character class.
An unexpected bashism .. Thanks for the tip!
After careful consideration, sed specifically uses regular-expressions not shell pattern matching, so, does that make this example a false positive ?
Before sending the string you are in shell land, at that point in time it is a shell pattern matching - the outcome of that is unknown. When you take the string and send it to sed you have left shell land and entered sed land, at that point in time it is a regular expression string.
By adding the quotes you will instruct the shell that it is a literal string and not a shell pattern.
By adding the quotes you will instruct the shell that it is a literal string and not a shell pattern.
Thanks for clarifying that point to me.