I needed to make some custom environment variables at the top of our
perl submit scripts, but sometimes perl doesn't seem to like some of
our settings. For instance, these [three] settings cause errors:
$ENV{APP_PLUGIN_DIR} = "c:\internal\our_app\libs"; # BAD
$ENV{APP_LICENSE_FILE} = "7700@licserve01"; # BAD
$ENV{PATH} = "\\isolan\apps\our_app\bin;$ENV{PATH}"; # BAD
Why doesn't perl like those settings?
Right; in Perl backslashes (\) and '@' are special characters, and
Perl allows those character's special meanings inside double quotes (").
They have to be 'escaped' to protect them from being interpreted
by perl. (Other shell languages like CSH and C need this too).
You can protect the meaning of those special characters by putting
a backslash escape in front of each special character, eg:
$ENV{APP_PLUGIN_DIR} = "c:\\internal\\our_app\\libs"; # OK
$ENV{APP_LICENSE_FILE} = "7700\@licserve01"; # OK
$ENV{PATH} = "\\\\isolan\\apps\\our_app\\bin;$ENV{PATH}"; # OK
Another approach is to replace the double quotes with single quotes,
as in these cases single quotes will properly protect the special
characters:
$ENV{APP_PLUGIN_DIR} = 'c:\internal\our_app\libs'; # OK
$ENV{APP_LICENSE_FILE} = '7700@licserve01'; # OK
$ENV{PATH} = '\\\\isolan\apps\our_app\bin;'.$ENV{PATH}; # OK
*But* there are caveats with single quotes esp. when double backslashes
are needed (like that 3rd line), such as with UNC paths:
$ENV{PATH} = '\\isolan\apps\our_app\bin;$ENV{PATH}"; # FAIL
That doesn't work, because perl still interprets \\ as an escape
sequence for a single backslash, even in single quotes. To get a
double backslash even in a single quoted string, you still have to
double up the backslashes:
$ENV{PATH} = '\\\\isolan\apps\our_app\bin;'.$ENV{PATH}; # OK
^^^^
Why, you may ask, does Perl need to support escaping a backslash
if single backslashes are already protected? Well, it's the only way
to insert a backslash at the *end* of a single quoted string, eg:
$foo = '\some\path\dir\'; # FAIL
$foo = '\some\path\dir\\'; # OK
The first line fails because that \' at the end makes perl think
you're trying to embed a single quote in the string. So for that
one case, Perl needs to be able to escape the meaning of the backslash,
hence the extra slash.
This is why I tell everyone to use FRONT SLASHES instead of
backslashes whenever possible, because there's nothing 'special'
about them:
$ENV{APP_PLUGIN_DIR} = "c:/internal/our_app/libs"; # OK
$ENV{PATH} = "//isolan/apps/our_app/bin;$ENV{PATH}"; # OK
This avoids all the hassles of backslashes being mistaken for
escape sequences.
This is all Microsoft's fault for choosing (and continuing to use)
backslashes as directory delimiters. It's caused nothing but trouble
for decades with C, C++ and shell script programs.
Fortunately Microsoft supports the use of front slashes at the
WIN32 kernel level, so in most cases (esp. with environment settings)
front slashes work equally well.
|