Reputation: 27
I am making a operating system in batch. I have a problem with the input system. If I enter a space (or multiple spaces) as an input, it shows an error that shouldn't be there. And I don't know how to fix it.
P.S. The line with if "%comm%"=="" goto loop
checks if the output is blank. And this is not the error maker.
@echo off
color a
:loop
set comm=
title %username%@%computername% : %cd%
set /p comm=[%username%@%computername%]
if "%comm%"=="" goto loop
if exist "%cd%"\%comm%.* (
call "%cd%"\%comm% 2>nul
)
goto error
:error
echo '%comm%' is not recognized as a programm or command.
goto loop
:nosw
@echo off
cls
echo Access Denied.
pause
Upvotes: 1
Views: 96
Reputation: 91
Okay, finally after reading this article about proper quoting of command line arguments, I came to this solution:
set comm=%comm: =^^ %
set comm=%comm:"=""%
This code is to be placed below your set /p ...
line and before your if...
condition. It precedes all spaces by the caret sign (1st line) and doubles all double quotes (2nd line). By this, no one of these characters will be treated as poison characters anymore.
Explanation
The caret sign (^) is used by the cmd.exe command line interpreter as the so called "line continuation character", which means to take the next character literally rather than interpret its (possibly) special meaning (including the special meaning of space characters to split up the commands on a command line).
From other discussions here in this thread: The square brackets "[]" are not handled as any special character at all. This is why it still fails when there are spaces inside.
In contrast to this, double quotes are indeed treated as special characters with the meaning that after the first found double quote the interpreter will interpret all upcoming text literally. But the interpreter will do the same only until it finds the next double quote, which is why the if
evaluation still fails on unbalanced double quotes. To prevent this, each double quote needs also to be doubled itself.
Hope this helps now.
Upvotes: 1
Reputation: 56188
you can tokenize your input (with space as delimiter) and reassemble them:
@echo off
setlocal enabledelayedexpansion
:loop
set "comm="
set /p "comm=[%username%@%computername%] "
set /a count=0
REM tokenize input:
for %%i in (%comm%) do (
set /a count+=1
set "word!count!=%%i"
)
REM check for empty input (or spaces only):
if %count% == 0 ( echo no valid input & goto :loop )
REM debug: show all words:
for /l %%i in (1,1,%count%) do echo [!word%%i!]
REM reassemble the words:
set "words="
for /l %%i in (1,1,%count%) do set "words=!words! !word%%i!"
REM remove first space (from assembling):
set "words=%words:~1%"
echo -%words%-
REM do with it whatever has to be done
goto :loop
This works, because two or more consecutive delimiters (spaces) are treated as one.
Upvotes: 0
Reputation: 56188
(sorry for writing it as an answer, no formatting possible in a comment)
@Marco both methods fail when there are unpaired quotes in the string; both work, if there are paired quotes. I still don't see any advantage using brackets, but in case of poison characters (even spaces!), qoutes work better.
C:\>if "a"b"c" == "a"b"c" echo paired quotes
paired quotes
C:\>if "a"b" == "a"b" echo unpaired quotes
"echo" kann syntaktisch an dieser Stelle nicht verarbeitet werden.
C:\>if [a"b"c] == [a"b"c] echo paired quotes
paired quotes
C:\>if [a"b] == [a"b] echo unpaired quotes
"echo" kann syntaktisch an dieser Stelle nicht verarbeitet werden.
C:\>if ""a"" == ""a"" echo parameter is already in quotes
parameter is already in quotes
C:\>if ["a"] == ["a"] echo parameter is already in quotes
parameter is already in quotes
C:\>if "a b" =="a b" echo poison character
poison character
C:\>if [a b] ==[a b] echo poison character
"b]" kann syntaktisch an dieser Stelle nicht verarbeitet werden.
for robvanderwoude's problem with %1
: easy to overcome by using if "%~1" == "hello"
(the ~
removes eventually surrounding quotes)
Upvotes: 1