"findstr" 使用 Batch 的问题
Issue with "findstr" using Batch
下面,我写了一些代码。它会检测 Micro-SD 卡是否已插入计算机,如果已插入,它会要求输入您的密码。输入 PIN 码后,它会在卡片中查找包含 PIN 码列表的文本文件。
:start
cls
echo.
echo.
if exist E:\ (
goto enterPin
) else (
echo INSERT YOUR CARD
)
timeout 1 >nul
goto start
:enterPin
echo Enter Account Pin: %chip%
set /p pin=": "
:: Finding the specified pin
findstr /m "%pin%" E:\Chip\CardInfo.txt >Nul
if %errorlevel%==0 (
echo Pin "%pin%" is valid
timeout 1 >nul
goto account
)
if %errorlevel%==1 (
echo Pin "%pin%" is invalid
pause
goto start
)
:account
cls
:: Finds the name of the account owner and continues
setlocal enableextensions disabledelayedexpansion
for /F "tokens=2 delims=/" %%a in ('findstr /I "%pin%/" E:\Chip\CardInfo.txt') do set "user=%%a"
for /F "tokens=3 delims=/" %%b in ('findstr /I "%pin%/%user%/" E:\Chip\CardInfo.txt') do set "balance=%%b"
echo.
echo.
echo Welcome, %user%.
echo.
echo ACCOUNT BALANCE: $%balance%
echo.
echo 1=Deposit / 2=Withdraw / 3=Exit / 4=Refresh
choice /c 1234 >nul
if %ERRORLEVEL% EQU 1 goto deposit
if %ERRORLEVEL% EQU 2 goto withdraw
if %ERRORLEVEL% EQU 3 exit
if %ERRORLEVEL% EQU 4 goto account
:deposit
echo.
echo.
set /p add="Money to Deposit: "
set /a moneytoadd=%balance%+%add%
call jrepl "%pin%/%user%/%balance%" "%pin%/%user%/%moneytoadd%" /f E:\Chip\CardInfo.txt /o -
goto account
:withdraw
echo.
echo.
set /p sub="Money to Withdraw: "
set /a moneytosub=%balance%-%sub%
call jrepl "%pin%/%user%/%balance%" "%pin%/%user%/%moneytosub%" /f
E:\Chip\CardInfo.txt /o -
goto account
endlocal
问题来了。一个 pin 由 4 个数字字符组成(例如 1234),但如果有两个具有相同字符的 pin(例如 1234, 6543),它会说该引脚有效。因此,例如,如果我键入 4,它只会在文件中查找数字 4。并会说密码有效。 尽管如此, 只是数字 4 不存在。我的猜测是这是“findstr”的缺陷。但我不确定。
“CardInfo.txt”的内容:
1234/Test User/1000
6543/Another Test User/2000
使用 REGEX(使用 <StartOfLine><PIN></>
):
findstr /m "^%pin%/" E:\Chip\CardInfo.txt >Nul
其中 ^
是“行首”。
这正是您想要的:
@echo off
::add your path below
for /f %%a in (file.txt) do (
call :funch %%a
)
:funch
set input=%1
set "modifiedinput=%input:~0,4%"
set /p pin=Enter Account Pin:
if %modifiedinput% equ %pin% ( goto authentication_passed) else ( goto authentication_failed)
:authentication_passed
echo auth passed
rem your code
pause >nul
exit
:authentication_failed
echo auth failed
goto funch
它将从文件中读取输入,然后提取前四个字符,在您的情况下就是 pin。
我重写了整个批处理文件以在执行时更加安全:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem endlocal is executed implicitly by cmd.exe on exiting batch file processing.
:Begin
cls
echo\
echo\
if exist E:\ goto enterPin
echo INSERT YOUR CARD
%SystemRoot%\System32\timeout.exe /T 1 >nul
goto Begin
:enterPin
set "pin="
set /p pin="Enter account pin for %chip%: "
if not defined pin goto enterPin
set "pin=%pin:"=%"
if not defined pin goto enterPin
for /F delims^=01234567890^ eol^= %%I in ("%pin%") do goto enterPin
rem Finding the specified pin.
%SystemRoot%\System32\findstr.exe /B /L /M /C:"%pin%/" E:\Chip\CardInfo.txt >Nul
if errorlevel 1 (
echo Pin "%pin%" is invalid.
pause
goto Begin
)
echo Pin "%pin%" is valid.
%SystemRoot%\System32\timeout.exe /T 1 >nul
:account
cls
rem Finds the name of the account owner and continues
for /F "tokens=2,3 delims=/" %%I in ('%SystemRoot%\System32\findstr.exe /B /L /C:"%pin%/" E:\Chip\CardInfo.txt') do set "user=%%I" & set "balance=%%J"
echo/
echo/
echo Welcome, %user%.
echo/
echo ACCOUNT BALANCE: $%balance%
echo/
echo 1=Deposit / 2=Withdraw / 3=Exit / 4=Refresh
%SystemRoot%\System32\choice.exe /c 1234 >nul
if not errorlevel 1 goto account
if errorlevel 4 goto account
if errorlevel 3 exit /B
if errorlevel 2 goto withdraw
:deposit
echo/
echo/
set "add="
set /P "add=Money to deposit: "
set /A moneytoadd=balance + add
call "%~dp0jrepl.bat" "%pin%/%user%/%balance%" "%pin%/%user%/%moneytoadd%" /L /f E:\Chip\CardInfo.txt /o -
goto account
:withdraw
echo/
echo/
set "sub="
set /P "sub=Money to withdraw: "
set /A moneytosub=balance - sub
call "%dp0jrepl.bat" "%pin%/%user%/%balance%" "%pin%/%user%/%moneytosub%" /L /f E:\Chip\CardInfo.txt /o -
goto account
此代码修复的问题:
- 有命令START。因此,不建议使用字符串
start
作为标签,尽管这是可能的。
- 建议避免 IF (...) ELSE (...) 如果一个简单的 IF 条件 GOTO 也可以使用。
- 尽可能使用完全限定文件名可以避免批处理文件在环境变量
PATH
(太频繁)或 PATHEXT
(很少)上损坏 运行用户的机器。
- 用户可以自由输入完成的提示
set /P
实际上,从无到有的任何东西都会导致语法错误的进一步处理,并立即退出未准备好的代码的批处理文件执行任何用户输入。出于这个原因,第一个 set /P
提示得到改进,并验证用户是否输入了仅由数字组成的字符串。
- FINDSTR 的用法是通过附加选项完成的,以便仅在行的开头查找 pin 区分大小写,并进行文字搜索,下一个字符必须是斜杠字符.
- 代码中使用了 ERRORLEVEL 求值的推荐语法。
- 算术表达式是使用推荐的语法编写的,即使用户不输入任何内容或输入根本无法转换为整数的字符串也能正常工作。
- 命令 EXIT 与选项
/B
一起使用仅退出批处理文件的处理,而不是整个命令过程。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
choice /?
cls /?
echo /?
findstr /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
timeout /?
关于代码改进的有用页面:
- How does the Windows Command Interpreter (CMD.EXE) parse scripts?
- Why is no string output with 'echo %var%' after using 'set var = text' on command line?
- DosTips 论坛主题:ECHO. FAILS to give text or blank line - Instead use ECHO/
- Single line with multiple commands using Windows batch file
- Safe number comparison in Windows batch file
下面,我写了一些代码。它会检测 Micro-SD 卡是否已插入计算机,如果已插入,它会要求输入您的密码。输入 PIN 码后,它会在卡片中查找包含 PIN 码列表的文本文件。
:start
cls
echo.
echo.
if exist E:\ (
goto enterPin
) else (
echo INSERT YOUR CARD
)
timeout 1 >nul
goto start
:enterPin
echo Enter Account Pin: %chip%
set /p pin=": "
:: Finding the specified pin
findstr /m "%pin%" E:\Chip\CardInfo.txt >Nul
if %errorlevel%==0 (
echo Pin "%pin%" is valid
timeout 1 >nul
goto account
)
if %errorlevel%==1 (
echo Pin "%pin%" is invalid
pause
goto start
)
:account
cls
:: Finds the name of the account owner and continues
setlocal enableextensions disabledelayedexpansion
for /F "tokens=2 delims=/" %%a in ('findstr /I "%pin%/" E:\Chip\CardInfo.txt') do set "user=%%a"
for /F "tokens=3 delims=/" %%b in ('findstr /I "%pin%/%user%/" E:\Chip\CardInfo.txt') do set "balance=%%b"
echo.
echo.
echo Welcome, %user%.
echo.
echo ACCOUNT BALANCE: $%balance%
echo.
echo 1=Deposit / 2=Withdraw / 3=Exit / 4=Refresh
choice /c 1234 >nul
if %ERRORLEVEL% EQU 1 goto deposit
if %ERRORLEVEL% EQU 2 goto withdraw
if %ERRORLEVEL% EQU 3 exit
if %ERRORLEVEL% EQU 4 goto account
:deposit
echo.
echo.
set /p add="Money to Deposit: "
set /a moneytoadd=%balance%+%add%
call jrepl "%pin%/%user%/%balance%" "%pin%/%user%/%moneytoadd%" /f E:\Chip\CardInfo.txt /o -
goto account
:withdraw
echo.
echo.
set /p sub="Money to Withdraw: "
set /a moneytosub=%balance%-%sub%
call jrepl "%pin%/%user%/%balance%" "%pin%/%user%/%moneytosub%" /f
E:\Chip\CardInfo.txt /o -
goto account
endlocal
问题来了。一个 pin 由 4 个数字字符组成(例如 1234),但如果有两个具有相同字符的 pin(例如 1234, 6543),它会说该引脚有效。因此,例如,如果我键入 4,它只会在文件中查找数字 4。并会说密码有效。 尽管如此, 只是数字 4 不存在。我的猜测是这是“findstr”的缺陷。但我不确定。
“CardInfo.txt”的内容:
1234/Test User/1000
6543/Another Test User/2000
使用 REGEX(使用 <StartOfLine><PIN></>
):
findstr /m "^%pin%/" E:\Chip\CardInfo.txt >Nul
其中 ^
是“行首”。
这正是您想要的:
@echo off
::add your path below
for /f %%a in (file.txt) do (
call :funch %%a
)
:funch
set input=%1
set "modifiedinput=%input:~0,4%"
set /p pin=Enter Account Pin:
if %modifiedinput% equ %pin% ( goto authentication_passed) else ( goto authentication_failed)
:authentication_passed
echo auth passed
rem your code
pause >nul
exit
:authentication_failed
echo auth failed
goto funch
它将从文件中读取输入,然后提取前四个字符,在您的情况下就是 pin。
我重写了整个批处理文件以在执行时更加安全:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem endlocal is executed implicitly by cmd.exe on exiting batch file processing.
:Begin
cls
echo\
echo\
if exist E:\ goto enterPin
echo INSERT YOUR CARD
%SystemRoot%\System32\timeout.exe /T 1 >nul
goto Begin
:enterPin
set "pin="
set /p pin="Enter account pin for %chip%: "
if not defined pin goto enterPin
set "pin=%pin:"=%"
if not defined pin goto enterPin
for /F delims^=01234567890^ eol^= %%I in ("%pin%") do goto enterPin
rem Finding the specified pin.
%SystemRoot%\System32\findstr.exe /B /L /M /C:"%pin%/" E:\Chip\CardInfo.txt >Nul
if errorlevel 1 (
echo Pin "%pin%" is invalid.
pause
goto Begin
)
echo Pin "%pin%" is valid.
%SystemRoot%\System32\timeout.exe /T 1 >nul
:account
cls
rem Finds the name of the account owner and continues
for /F "tokens=2,3 delims=/" %%I in ('%SystemRoot%\System32\findstr.exe /B /L /C:"%pin%/" E:\Chip\CardInfo.txt') do set "user=%%I" & set "balance=%%J"
echo/
echo/
echo Welcome, %user%.
echo/
echo ACCOUNT BALANCE: $%balance%
echo/
echo 1=Deposit / 2=Withdraw / 3=Exit / 4=Refresh
%SystemRoot%\System32\choice.exe /c 1234 >nul
if not errorlevel 1 goto account
if errorlevel 4 goto account
if errorlevel 3 exit /B
if errorlevel 2 goto withdraw
:deposit
echo/
echo/
set "add="
set /P "add=Money to deposit: "
set /A moneytoadd=balance + add
call "%~dp0jrepl.bat" "%pin%/%user%/%balance%" "%pin%/%user%/%moneytoadd%" /L /f E:\Chip\CardInfo.txt /o -
goto account
:withdraw
echo/
echo/
set "sub="
set /P "sub=Money to withdraw: "
set /A moneytosub=balance - sub
call "%dp0jrepl.bat" "%pin%/%user%/%balance%" "%pin%/%user%/%moneytosub%" /L /f E:\Chip\CardInfo.txt /o -
goto account
此代码修复的问题:
- 有命令START。因此,不建议使用字符串
start
作为标签,尽管这是可能的。 - 建议避免 IF (...) ELSE (...) 如果一个简单的 IF 条件 GOTO 也可以使用。
- 尽可能使用完全限定文件名可以避免批处理文件在环境变量
PATH
(太频繁)或PATHEXT
(很少)上损坏 运行用户的机器。 - 用户可以自由输入完成的提示
set /P
实际上,从无到有的任何东西都会导致语法错误的进一步处理,并立即退出未准备好的代码的批处理文件执行任何用户输入。出于这个原因,第一个set /P
提示得到改进,并验证用户是否输入了仅由数字组成的字符串。 - FINDSTR 的用法是通过附加选项完成的,以便仅在行的开头查找 pin 区分大小写,并进行文字搜索,下一个字符必须是斜杠字符.
- 代码中使用了 ERRORLEVEL 求值的推荐语法。
- 算术表达式是使用推荐的语法编写的,即使用户不输入任何内容或输入根本无法转换为整数的字符串也能正常工作。
- 命令 EXIT 与选项
/B
一起使用仅退出批处理文件的处理,而不是整个命令过程。
为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。
call /?
choice /?
cls /?
echo /?
findstr /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
timeout /?
关于代码改进的有用页面:
- How does the Windows Command Interpreter (CMD.EXE) parse scripts?
- Why is no string output with 'echo %var%' after using 'set var = text' on command line?
- DosTips 论坛主题:ECHO. FAILS to give text or blank line - Instead use ECHO/
- Single line with multiple commands using Windows batch file
- Safe number comparison in Windows batch file