I'm working with a batch file and I was wondering, why do some variables have double quotes around them and others don't, for example?
SET "keePass=%USERPROFILE%\KeePass\KeePass-2.31\KeePass.exe"
but this:
SET name="bob"
Why the double quotes in the first one, but not the second?
...to provide the conclusion at the beginning:
Supposing you have got the command extensions enabled (which is the default setting of the Windows command prompt cmd), the best practice is to use the following set syntax:
set "VAR=value"
(The command extensions can be enabled/disabled by cmd (type cmd /? in a command prompt window for help) or, within batch files only, by setlocal (type setlocal /? for details).)
At first, let us take a look at the standard syntax mentioned in the help text, that appears when typing set /? (or help set) in a command prompt window:
set VAR=value
This assigns the string value to the variable VAR obviously.
The good thing of this syntax is:
it also works when the command extensions are disabled;
the variable value is not surrounded by quotation marks (supposing value does not contain such on its own), so there is only one place to take care of them, namely during variable expansion (like %VAR% or "%VAR%", depending on the situation at hand; this is particularly useful when combining strings like constant_%VAR% or "constant_%VAR%", which will be expanded to constant_value or "constant_value", respectively, so you always have full control over the placement of the quotation marks; if the value contained the enclosing "", constant_%VAR% would expand to constant_"value", which might probably not be the string you want to have);
But there might occur some problems:
any (invisible) trailing white-space becomes part of the string value, so if the command line is followed by a single SPACE character, VAR will carry the value valueSPACE;
when you concatenate this command with another command, like set VAR=value & echo Text, the SPACE before the & character becomes part of the value; you could of course write set VAR=value&echo Some text, but this was quite difficult to read;
if value contains special characters, like ^ & ( ) < > |, you might run into problems; for example, set VAR=1&2 will assign 1 to VAR, then an error will arise, because & separates two commands and 2 is not a valid one;
The syntax of the second example in your question is quite similar:
set VAR="value"
This assigns the string "value" to VAR, so the quotation marks are included in the value.
The advantages are:
it also works when the command extensions are disabled;
special characters (like ^ & etc.) in value do not cause any trouble because of the "";
But still:
the quotation marks become part of the value, which may be disturbing in numerous situations;
unwanted trailing white-spaces (after the last ") still become part of the string value;
again when concatenating this command with another command using &, you have to omit spaces around the ampersand;
Now, let us check out the syntax of the first example in your question:
set "VAR=value"
This assigns value to VAR. Since the quotation marks are placed around the entire assignment expression, they are removed before the assignment is actually accomplished.
This has got several advantages:
the quotation marks do not become part of the variable value;
any (unintended) trailing white-spaces do not become part of the variable value;
you can concatenate it with another command using SPACE&SPACE without any unwanted spaces being appended to the value;
special characters (like ^ & etc.) in value are no problem;
But there is one issue:
the command extensions need to be enabled for this syntax to work; otherwise, an error arises;
Finally, you could also combine the above syntaxes, if you do want the quotation marks to become part of the variable value (although I do not recommend that):
set "VAR="value""
This assigns "value" to VAR.
Advantages:
unwanted trailing white-spaces (after the last ") do not become part of the variable value;
you can concatenate it with another command using SPACE&SPACE without any unwanted trailing spaces in the value;
Disadvantages:
the quotation marks become part of the value, which may be disturbing in numerous situations;
the command extensions need to be enabled for this syntax to work; otherwise, an error arises;
special characters (like ^ & etc.) in value may cause problems; this is because of the way the command parser works: as soon as the first " is encountered, any special characters are no longer recognised, they are treated as literal characters; after the next ", special character recognition becomes re-activated, and so on; regard that this is also true in case value itself contains any quotation marks on its own;
Side Note:
Never put spaces around the equal-to sign in a set command line, because they will become part of the variable name and/or value. For instance, the command lines
set VAR = value
and
set "VAR = value"
both assign the string value SPACEvalue to a variable named VARSPACE.
Related
For a gradle script, I am composing strings that will be used as command line for a subsequent gradle Test-task. One of the strings is the user's password, which eventually will be passed to the called (exec'ed) "java ..." call using the JVM's -D option, e.g. -Dpassword=foobar.
What complicates things here is, that this password can/should of course contain special characters, that may interfere with the use of the string as command line. In other words: I need to escape special characters (which is OS-specific). :-(
Now to my actual question:
I want to use the String.replaceAll method, i.e. replaceAll(list_of_special characters, EscapeCharacter + Ref_to_matched_character),
e.g. simplified something like replaceAll("[#$%^&]", "^$1")
'^' meaning the escape character and '$1' meaning the matched character here.
Is that possible, i.e. can one refer to the matched pattern in the second argument of replaceAll?
Is that possible, i.e. can one refer to the matched pattern in the second argument of replaceAll?
yes, it's possible
'a#b$c'.replaceAll('([#$%^&])', '^$1')
returns
a^#b^$c
Thanks for the responses and the reviews improving readability. Meanwhile I got my expression working. For those interested:
// handles gthe following: `~!##$%^&*()_+-={}|[]\:;"'<>?,./
escaped = original.replaceAll('[~!##\\$\\%\\^\\&\\*\\(\\)_\\+-={}\\|\\[\\]\\\\:;\"\\\'<>\\?,\\./]', '^$0') // for Windows - cmd.exe
I'm trying to write a SQL script for use in SQL plus using substitution variables defined at runtime. Is there a way to actively escape any special characters coming in?
For instance, if the variable has an ' in it, it will immediately break whatever line in the script is running it with a
ORA-01756: quoted string not properly terminated
error since I didn't complete the quote or completed it too early. I just want it to treat the variable as a string. Is there a way to tell Oracle to just treat the characters literally to set a field or similar?
In my specific case, I want to make a general case script to change a password by prompting for the user, old, and new password.
connect &&myuser/&&oldpass#mydb;
alter user &&myuser identified by &&newpass replace &&oldpass;
If the old or new password contains special characters, it could break for a plethora of reasons, including the issue I have above.
No, there is no way to escape characters in substitution variable values.
SQL*Plus substitution variables (those of type CHAR, the only other types are numeric) are always substituted verbatim. SQL*Plus pays no attention to the structure of the statements in which substitution variables appear: it just does a search-and-replace of the variables with their values, irrespective of whether doing that leaves a valid SQL statement afterwards.
From the make documentation
Since trailing space characters are not stripped from variable values,
just a space at the end of the line would have the same effect (but be
rather hard to read). If you put whitespace at the end of a variable
value, it is a good idea to put a comment like that at the end of the
line to make your intent clear. Conversely, if you do not want any
whitespace characters at the end of your variable value, you must
remember not to put a random comment on the end of the line after some
whitespace, such as this:
dir := /foo/bar # directory to put the frobs in\
Here the value of the variable dir is ‘/foo/bar ’ (with four
trailing spaces), which was probably not the intention. (Imagine
something like ‘$(dir)/file’ with this definition!)
Is there a way to allow make to parse dir properly so that it is just /foo/bar? Or has the entire make community just accepted that you are not allowed to have comments on the same line with spaces separating them?
seems kind of silly considering end-of-line comments are very useful
I'm looking over a script (which has been used successfully in the past) which contains the following:
node=1
while :
do
userKey=WEB_${node}_USER
userVal=`echo ${!userKey}`
I have not been able to figure out why an exclamation point would be added to a variable reference like this. What purpose does "!" serve in this context?
It's rare for me to do much scripting so if I am missing any details please let me know and I will try to provide more information. I have not been able to find this answer elsewhere.
Thanks in advance!
It's called indirect parameter expansion. Where $userKey expands to the value of the variable userKey, ${!userKey} expands to the value of the variable whose name is the value of userKey. Since usrKey has the value WEB_1_USER (given the current value of $node, ${!userKey} expands to the same result as $WEB_1_USER.
Its use is somewhat rare, since in many cases (including, it appears, here) an array WEB_USER of user names would be clearer than a set of numbered variables.
WEB_USER=(alice bob charlie)
node=1
while :
do
userVal=${WEB_USER[node]}
In bash, I thought that the only characters that retained their meta-character status inside double quotes were the dollar sign ($), the back-tick (`) and the backslash (\).
I'm trying to write a bash completion function that works for strings containing spaces and punctuation, even quotes may be in there.
I extract these strings with sed from files and thus have them as a several lines of text where each one contains a target string for completion. However, all the ways I tried to pass this to compgen -W, I always get completion for the individual words only.
There is a variable COMP_WORDBREAKS that defines which characters are treated as words' separators. Tuning this variable you can try to achieve what you want.
From bash(1):
COMP_WORDBREAKS — The set of characters that the Readline library treats as word separators when performing word completion. If COMP_WORDBREAKS is unset, it loses its special properties, even if it is subsequently reset.