Problems checking if string is quoted and adding quotes to string

自作多情 提交于 2021-02-16 05:18:08

问题


I am trying to check if a string is quoted by checking the first and last characters of the string. But my script fails when checking for the quote see output: AND was unexpected at this time. below.

Code

@echo off

set mystring=Non quoted string

set myquotedstring=^"My quoted string^"

echo mystring: %mystring%

echo myquotedstring: %myquotedstring%

set result=%mystring:~0,1%

echo first character of non quoted string is: %result%

set result=%mystring:~-1%

echo last character of non quoted string is: %result%

if %mystring:~0,1%u==^" AND %mystring:~-1%==^" (
   echo this string is NOT quoted
   set newstring=^"Non quoted string^"
   echo newstring: %newstring%
)

set result=%myquotedstring:~0,1%

echo first character of quoted string is: %result%

set result=%myquotedstring:~-1%

echo last character of quoted string is: %result%

if %myquotedstring:~0,1%u==^" AND %myquotedstring:~-1%==^" (
   echo this string is quoted
)

This is the output I am getting

mystring: Non quoted string
myquotedstring: "My quoted string"
first character of non quoted string is: N
last character of non quoted string is: g
this string is NOT quoted
newstring: "Non quoted string"
first character of quoted string is: "
last character of quoted string is: "
AND was unexpected at this time.

UPDATE

I realise now I cannot use AND. But even if I remove I have a problem.

eg

if %mystring:~0,1%u==^" if %myquotedstring:~-1%==^" (
   echo this string is NOT quoted
   set newstring=^"Non quoted string^"
   echo newstring: %newstring%
)

I get

The syntax of the command is incorrect.

回答1:


@echo off
setlocal EnableDelayedExpansion

set mystring=Non quoted string
echo %mystring%
if !mystring:~0^,1!!mystring:~-1! equ "" (
   echo -^> String is quoted
) else (
   echo -^> String not quoted
   set newstring="%mystring%"
   echo New string: !newstring!
)
echo/

set mystring="My quoted string"
echo %mystring%
if !mystring:~0^,1!!mystring:~-1! equ "" (
   echo -^> String is quoted
) else (
   echo -^> String not quoted
   set newstring="%mystring%"
   echo New string: !newstring!
)



回答2:


I corrected the syntax error you got. It was probably because of wrong escape sequence. You should've used "" instead of ^" due to this documentation. But it didn't work for me too, it's little tricky to deal with double quotes.

Personally, I replace " with + or some other character before manipulating a string. So this piece of code works fine:

set myquotedstring="My quoted string"

set firstChar=%myquotedstring:~0,1%
set lastChar=%myquotedstring:~-1%

:: Replace " with +
set firstChar=%firstChar:"=+%
set lastChar=%lastChar:"=+%

if "%firstChar%"=="+" if "%lastChar%"=="+" (
    echo "myquotedstring is quoted"
)



回答3:


there is no AND in batch. Use

if var1==value1 if var2==value2 echo both ok

instead.




回答4:


A very simple check is done with a case-sensitive string comparison of the value of an environment variable like mystring with another environment variable like MyStringCheck which is defined before with the value of mystring with all double quotes substituted by an empty string resulting in removal of all double quotes.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "mystring=Non quoted string"
set "myquotedstring="My quoted string""
setlocal EnableDelayedExpansion

set "_StringCheck=!mystring:"=!"
if !mystring! == !_StringCheck! (
       echo mystring is defined with NOT quoted string: !mystring!
) else echo mystring is defined with quoted string: !mystring!
set "mystring="!_StringCheck!""

set "_StringCheck=!myquotedstring:"=!"
if !myquotedstring! == !_StringCheck! (
       echo myquotedstring is defined with NOT quoted string: !myquotedstring!
) else echo myquotedstring is defined with quoted string: !myquotedstring!
set "myquotedstring="!_StringCheck!""

rem Output the two environment variables after string checking.
echo/
echo The environment variables mystring and myquotedstring are now:
echo/
set my

endlocal
endlocal

This code without the not necessary IF conditions:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "mystring=Non quoted string"
set "myquotedstring="My quoted string""
setlocal EnableDelayedExpansion
set "mystring="!mystring:"=!""
set "myquotedstring="!myquotedstring:"=!""
echo The environment variables mystring and myquotedstring are:
echo/
set my
endlocal
endlocal

Why do you want to check if a string is quoted and add quotes at all?

It is nearly always better to have strings assigned to environment variables without quotes and use the quotes in the batch file where it must be done on referencing the value of the environment variable, but reference the environment variable value without quotes when that is not wanted like on an ECHO line.

The other answers contain solutions to easily check if a string assigned to an environment variable is enclosed in " or not, but none of them handle the rare use cases that the string assigned to an environment variable has only one " either at beginning or at end, or the string assigned to an environment variable has only one character at all which is perhaps even ".

It is easy to control by the author of a batch file how the string assigned to the environment variable looks like on this string being written in the batch file itself. But if the string is passed to the batch file via an argument string or a user is prompted for a string assigned to an environment variable, there must be additional code used to make the batch file execution fail safe on by mistake incorrect user input or argument strings.

Example:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem Example for processing an argument.
set "FirstArgument=%~1"
if defined FirstArgument set "FirstArgument=%FirstArgument:"=%"
setlocal EnableDelayedExpansion
echo First argument without quotes is:  !FirstArgument!
endlocal
echo First argument with quotes is:    "%FirstArgument%"

rem Example for processing a user input.
set "UserInput=""
set /P "UserInput=Please enter something: "
set "UserInput=%UserInput:"=%"
setlocal EnableDelayedExpansion
echo User input without quotes is:  !UserInput!
endlocal
echo User input with quotes is:    "%UserInput%"

endlocal

In this example first the required execution environment is defined completely by the first two command lines which is:

  • command echo mode disabled
  • command extensions enabled
  • delayed environment variable expansion disabled

The command SETLOCAL does not push only the current status of command extensions and delayed expansion on stack before enabling command extensions and disabling delayed expansion according to the two used options, but makes also a copy of all environment variables defined already on starting the batch file. This newly created environment variables list is used for the rest of the batch file. SETLOCAL pushes also the path of current directory on stack.

The command ENDLOCAL at end of the batch file restores the previous execution environment which means the status of command extensions and delayed expansion are popped from stack and set accordingly. Further the created environment variables list is discarded and the initial environment variables list is restored which means the environment variables FirstArgument and UserInput do not exist anymore after processing of this batch file finished respectively have their initial values on starting the batch file in case of existing already on starting the batch file. There is also popped from stack the current directory path and this directory is set again as current directory if still existing on execution of command ENDLOCAL.

Delayed environment variable expansion is disabled as otherwise arguments passed to the batch file containing one or more exclamation marks would be processed wrong by this demonstration batch file. Any file/folder name can contain character ! one or more times.

Processing of an argument string passed to the batch file

A batch file like Test.cmd can be started as follows:

  1. Test.cmd
    The batch file is started without an argument string passed to the batch file which means %1 is replaced by an empty string.
  2. Test.cmd C:\Temp\Example.txt
    The batch file is started with an argument string which is not enclosed in double quotes.
  3. Test.cmd "C:\Temp\ ;%Development & Test!.txt"
    The batch file is started with an argument string which is enclosed in double quotes.
  4. Test.cmd "C:\Temp\Common File Name.txt
    The batch file is started with an argument string where by mistake only " at beginning exists, but " at end of the argument string is missing.
  5. Test.cmd C:\Temp\FileName.txt"
    The batch file is started with an argument string where by mistake the " at beginning is missing, but " at end of the argument string exists.
  6. Test.cmd ""
    The batch file is started with an empty argument string. This happens usually if an executable or another batch file starts the batch file which contains in code a mistake resulting in starting the batch file with the double quotes around first argument string, but the argument string is missing.
  7. Test.cmd "
    The batch file is started with just one double quote character. This could happen on a user with a German or a British keyboard wanted to start the batch file with 2 as argument, but pressed Shift+2 or CapsLock was enabled on pressing key 2 and the user hit too quickly RETURN or ENTER to execute the command line.

It is important to know that there is no possibility to pass an argument string to a batch file which contains inside " and which cmd.exe should interpret as literal character. Linux shell interpreters support that by using other quotes around an argument strings, but not Windows cmd.exe.

In most batch files is used just "%~1" explained by the help output on running in a command prompt window call /?. That works for most uses cases, but not for all as it can be seen on testing such batch files with the seven examples above.

The posted batch file assigns the first argument to the environment variable FirstArgument with letting cmd.exe remove the surrounding double quotes.

The environment variable FirstArgument is not defined for first, sixth and last example as %~1 is replaced in this case by an empty string and so set "FirstArgument=" is executed which results in deletion of the environment variable if existing at all.

The environment variable FirstArgument is defined for second, third and fourth example with the passed argument string with no double quotes.

But cmd.exe does not remove " at end of an argument string on usage of %~1 if the argument string does not have " at the beginning. So for the very unusual fifth use case there is extra code needed to handle such argument strings also correct without causing later an exit of batch file processing due to a syntax error because of the " at end of the string.

The solution for fifth use case is removing explicitly all " from string assigned to environment variable FirstArgument if this environment variable is defined at all.

The characters which require a string to be quoted are listed in help of cmd output on last help page displayed on running cmd /? in a command prompt window which are a space or one of these characters &()[]{}^=;!'+,`~. If an argument string should be passed to a batch file containing the redirection operators <>| being interpreted as literal characters, for example a password string, the argument string must be also enclosed in double quotes.

It is very important that the assignment to the environment variable FirstArgument is done with the argument variable=value of command SET being enclosed in double quotes. The usage of just set FirstArgument=%~1 is not fail safe. Why using set "variable=value" is explained for example here.

Processing of string input by a user on prompt

The same care should be taken on using in a batch file set /P as on processing of an argument string because of the user can enter really anything. A user can

  • enter nothing at all or
  • enter a string containing one or more " and/or
  • enter a string containing operators like &<>|.

The environment variable specified on set /P command line is either still undefined on not existing already before prompt or still unmodified on existing already before prompt in case of the user hits on prompt just RETURN or ENTER.

For that reason it is good practice to define an environment variable before prompting the user with a useful default string or check with an if defined variable condition immediately after the set /P command line if the user entered anything at all and handle this use case accordingly.

The environment variable UserInput is defined before prompt with a single " as value in the demo code. So if the user enters nothing, the environment variable UserInput is still defined with just " as value.

The command line after set /P removes all " from the user input string. The result can be now that the environment variable UserInput is not defined anymore after this command line. This should be always taken into account. It is good practice to use normally (once again) if defined variable to handle this use case of environment variable not defined anymore after removing all double quotes.

Output of an environment variable string with ECHO

A string assigned to an environment variable can be processed further safely after removing all double quotes on enclosing the argument string containing the environment variable reference %variable% itself in double quotes.

But sometimes the string assigned to an environment variable like a file or folder name without or with path should be output with command ECHO to console window or a file and that should be done without enclosing the environment variable reference in double quotes.

This is tricky as a file/folder name can contain characters like & being interpreted as operator by cmd.exe outside a double quoted argument string or ! being interpreted as start/end of an environment variable reference on delayed environment variable expansion enabled at the moment.

The third argument example is really good to test a batch file because of the file name starts with two leading spaces, contains next a semicolon and a percentage sign, contains additionally an ampersand and an exclamation mark. A batch file being entitled to work with any file/folder names must be coded very good to correct handle such a file name.

The demo code outputs the argument string respectively the user input without double quotes for that reason with using temporarily delayed environment variable expansion to avoid that the string passed to the batch file respectively entered by the user modifies the ECHO command line finally executed by cmd.exe. It can be seen on testing the demonstration batch file that the very unusual file name C:\Temp\ ;%Development & Test!.txt is output without double quotes without causing any troubles.

It is of course easier and therefore much better to output a file/folder name of unknown consistence with enclosing it in double quotes. So every batch file printing with ECHO information containing a file/folder name read directly from the file system or passed to the batch file as argument or entered by a user on a prompt should enclose the file/folder name better in double quotes. Then it is also easier to see for a user where a file/folder name begins and ends, especially if the file/folder name is output without path and having leading spaces.



来源:https://stackoverflow.com/questions/31358869/problems-checking-if-string-is-quoted-and-adding-quotes-to-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!