问题
A while ago I made a function that you can call from the command prompt or any batch file (it was just for fun, I don't see how it could be useful). It basically just makes your (Microsoft) computer speak whatever you wrote in as the parameter. I recently got some inspiration to add a switch to it where it would read the contents of a file. My standalone script worked, but when I added it to my function, it didn't work as I would have liked.
Here's the code:
@echo off & setlocal enabledelayedexpansion
if "%~1"=="/?" (
echo.
echo TALK "Text" [Parameters]
echo.
echo Text - The phrase you want to be spoken.
echo.
echo [Parameters]:
echo /f - Read the contents of a file. "Text" changes to the file path.
echo.
endlocal
exit /b
)
if "%~2 X" equ "/f X" (
if not exist %~1 (
echo File does not exist or cannot be found.
endlocal
exit /b
)
set cont=
for /f "delims=" %%i in (%~1) do set cont=!cont! %%i
:b
echo Set a = Wscript.CreateObject("SAPI.SpVoice") > "Talk.vbs"
echo a.speak "%cont%" >> "Talk.vbs"
start /WAIT Talk.vbs
del Talk.vbs
endlocal
exit /b
)
set text=%~1
echo set speech = Wscript.CreateObject("SAPI.spVoice") > "talk.vbs"
echo speech.speak "%text%" >> "talk.vbs"
start /WAIT talk.vbs
del Talk.vbs
endlocal
exit /b
Unfortunately I don't have working function code (before I added the /f
switch).
This is a last resort for me as I've edited it heavily and scoured the code for any give away as to what the problem might be.
Another bad thing is that I didn't take note of what I changed, so I can't exactly tell you what I've tried. I can tell you what the outputs are though.
The first time I tried, it gave the output The syntax of the command is incorrect.
It's now at the point where the original function (just converting text to speech) doesn't work anymore. The contents of the file Talk.vbs
(which was made during the process) is a.speak ""
.
I'll keep updating my attempts, but knowing me it's something really simple that I've overlooked.
--EDIT-- At the suggestion of someone, I put carats before the square brackets in the syntax section. Nothing changed.
回答1:
Along with escaping the parenthesis you also had to surround if exist %~1
in quotes in case of a argument of "some words I want it to say"
. Also cleaned it up a bit. Code at the bottom, but first an explanation.
If you looked at talk.vbs before it was deleted you would see this:
a.speak "!cont! contents of the file here"
This is because of this code:
for /f "delims=" %%i in (%~1) do set cont=!cont! %%i
:b
echo Set a = Wscript.CreateObject("SAPI.SpVoice") > "Talk.vbs"
If you turned echo on and watched the code you would see the last unescaped )
was taking the contents of the for loop and including it in the redirect.
Corrected and cleaned code:
@echo off & setlocal enabledelayedexpansion
if "%~1"=="/?" (
echo.
echo TALK "Text" [Parameters]
echo.
echo Text - The phrase you want to be spoken.
echo.
echo [Parameters]:
echo /f - Read the contents of a file. "Text" changes to the file path.
echo.
endlocal
exit /b
)
set text=
if [%2]==[/f] (
if exist "%~1" (
for /f "usebackq delims=" %%i in (%1) do set text=!text! %%i
) else (
endlocal
exit /B
)
)
if [%2]==[] set text=%~1
echo set speech = Wscript.CreateObject^("SAPI.spVoice"^) > "talk.vbs"
echo speech.speak "%text%" >> "talk.vbs"
cscript //NoLogo //B talk.vbs
del Talk.vbs
endlocal
exit /b
Edit: fixed the for
statement pointed out by Andriy M
回答2:
In your echo statements that contain parentheses, try escaping the parentheses with carats. I suspect especially the echo within the if statement is partially getting evaluated literally.
One other minor suggestion, I would also replace
start /WAIT Talk.vbs
with
cscript /nologo Talk.vbs
It's not that I think the start /wait
is causing the error, but it does cause a second console window to appear temporarily for no good reason -- or it will whenever your script executes that far, anyway.
I made a few other suggested changes here, such as eliminating the need for a /f switch. If "%1" is the name of a file that exists, read it. Otherwise, treat it as text to read. And instead of having a separate subroutine for reading a file versus getting text from input, all that needs to happen is a variable has a different value.
@echo off & setlocal enabledelayedexpansion
if "%1"=="/?" ( goto usage )
if "%1"=="" ( goto usage )
if "%1"=="--help" ( goto usage )
if exist "%1" (
set txt=
for /f "usebackq tokens=*" %%i in (%1) do set txt=!txt! %%i
) else (
set txt=%1
)
echo Set a = Wscript.CreateObject^("SAPI.SpVoice"^) > "talk.vbs"
echo a.speak "%txt%" >> "talk.vbs"
cscript /nologo talk.vbs
del talk.vbs
endlocal
goto :EOF
:usage
echo.
echo TALK ["text"^|filename]
echo.
echo talk filename -- speaks the contents of filename
echo talk "text" -- speaks the supplied text
endlocal
goto :EOF
来源:https://stackoverflow.com/questions/14793998/batch-function-not-working-correctly