Batch File to edit specific line of Text file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
T3RRY
Posts: 83
Joined: 06 May 2020 10:14

Re: Batch File to edit specific line of Text file

#31 Post by T3RRY » 16 Oct 2020 20:46

werejago wrote:
16 Oct 2020 16:14
Hey T3rry after testing it out again I didn't run into the same issue I'm thinking I had the wrong directory that was causing my previous issue.
I can't thank you enough for all the help. I'll get back to you after further testing. Also, are you involved with cryptocurrency? I would love to tip you for your efforts.

Thanks again.
Thanks for the thought, but the thanks itself is enough.

werejago
Posts: 21
Joined: 01 Oct 2020 07:43

Re: Batch File to edit specific line of Text file

#32 Post by werejago » 19 Oct 2020 08:31

Hey T3rry I noticed the script doesn't restrict past the maximum allowed "26H16" (0-26)(A-H)(0-16) for ex I could enter "99H99" when the highest position the script goes is "26H16".

What would be the easiest way of going about this do you think?

T3RRY
Posts: 83
Joined: 06 May 2020 10:14

Re: Batch File to edit specific line of Text file

#33 Post by T3RRY » 21 Oct 2020 10:00

easiest way is to use findstr to check the entered string is in the sensor serialisation file and use conditional operator || to loop back to retry if not

I've modifying the script to pass the character range for the Serial # in the format used by findstr, to display remaining serial numbers that match the range in the file on incorrect input:

Code: Select all

:retry
%Input%
IF "%~2" == "5" (
 (Type "!File!"| findstr.exe /BLIC:"!nVar!" > nul 2> nul ) || (
  Echo/ Invalid value for %1. range: %~4
  Type "!File!"| findstr.exe /BR "%~4" 2> Nul
  Goto :Retry
 )
)
full script

Code: Select all

@echo off & CD "%~dp0" & Goto :Main
rem /*_________________________________________Functions; sets parameters, sets input, verfies input to parameters */
:GetIN [ReturnVar] [Length] [Allowed Characters] [Format]
Setlocal EnableDelayedExpansion
Set "Input=(Set "nVar="&Echo/Enter %2 Digit %1 %~4:&(For /L %%. in (1 1 %2)Do For /F "Delims=" %%G in ('Choice /N /C %3')Do (<Nul Set /P"=%%G"&Set "nvar=^^!nVar^^!%%G"))&Echo/&If not "%~2" == "5" (Echo/Confirm: ^^!nVar^^! Y/N & For /F "Delims=" %%v in ('Choice /N')Do (If /I "%%~v"=="n" (Goto :retry))))"
:retry
%Input%
IF "%~2" == "5" (
 (Type "!File!"| findstr.exe /BLIC:"!nVar!" > nul 2> nul ) || (
  Echo/ Invalid value for %1. range: %~4
  Type "!File!"| findstr.exe /BR "%~4" 2> Nul
  Goto :Retry
 )
)
Echo/%1 [!nVar!] Confirmed
Endlocal & Set "%1=%nVar%" 2> Nul
Exit /B 0
:UpdateWO
 <"!file!" set /p "line1="
 >"!file!.~tmp" Echo/!line1!
 >>"!file!.~tmp" echo/!#WO!
 <"!file!" >>"!file!.~tmp" more +2
 move /y "!file!.~tmp" "!file!"
Exit /B
:UpdateSER
 <"!File!" (
  Set /P "Line[1]="
  Set /P "Line[2]="
  Set /P "Line[3]="
 )
 >"!File!.~tmp" (
  Echo/!Line[1]!
  Echo/!Line[2]!
  Echo/!Line[3]!
  Echo/!#SER!
 )
Set "Start=F"
(For /F "UsebackQ Skip=3 Delims=" %%G in ("!File!")Do If not "%%~G" == "!#SER!" (If "!Start!" == "T" (Echo/%%~G))Else Set "Start=T") >>"%File%.~tmp"
move /y "!file!.~tmp" "!file!"
Exit /B
rem /*_________________________________________Script Body; reads/writes to Serialization.txt line 2 */ 
:Main
Set "Menu=Echo/[R]epeat [C]ontinue [E]xit&For /F "Delims=" %%G in ('Choice /N /C:RCE')Do If "%%G"=="R" ( Goto :lbl )Else If "%%G"=="E" (Endlocal & Exit /B 0)"
setlocal EnableDelayedExpansion
:WorkOrder
set "file=Sensor Serialization.txt"
Call :GetIn #WO 8 0123456789
rem /* Call function to update workorder # in file */
Call :UpdateWO
%menu:lbl=WorkOrder%
:Serial
Call :GetIn #SER 5 0123456789ABCDEFGH "[0-2][0-6][A-H][0-1][0-6]"
Call :UpdateSer
%menu:lbl=Serial%
rem /* Additions to your script should occur before this Endlocal */
Endlocal

werejago
Posts: 21
Joined: 01 Oct 2020 07:43

Re: Batch File to edit specific line of Text file

#34 Post by werejago » 21 Oct 2020 13:43

Thank you T3rry. Works like a charm!

T3RRY
Posts: 83
Joined: 06 May 2020 10:14

Re: Batch File to edit specific line of Text file

#35 Post by T3RRY » 22 Oct 2020 08:56

I've been playing around with it again, as using a findstr regular expression as an argument to the GetIn input function makes the length argument and the for loop choice method of input somewhat redundant.

The below uses only 2 arguments for the input function:
Arg1 - return var name.
Arg 2 - Findstr regular expresion pattern.

This allows Set /P to be used to take input, allowing the user to correct typos using backspace without having to finish keying in the string before looping back.

Calling getIn without a 2nd arg will display the help output of findstr relating to expression options for restricting input

Code: Select all

@echo off & CD "%~dp0" & Goto :Main
:GetIN [ReturnVar] ["qouted findstr search pattern"]  [Optional:"/C" - required for patterns with spaces] ::::::::::::
rem ::: [ GetIn Input function or standalone script for validating user
rem :::   input through the use of findstr regular expressions. ]
 SETLOCAL EnableExtensions EnableDelayedExpansion
(Set LF=^

%= Linefeed. do not modify. =%)
 Set "Exit.Code=0"
rem [ test if standalone script - if so test if accessed by pipe; reject execution if true ]
 If "%~0" == "%~n0" For %%G in (!cmdcmdline!)Do Echo/%%~G|Findstr.exe /LIC:"/S" > nul 2> nul && (
  Echo/===============================================================================================================
     Echo/*******************************             ^^! pipes not supported ^^!             *******************************
  Set "Exit.Code=2" & Goto :Usage
 ) else rem ::: [ Is a function - pipetest will likely fail. Exit.Code prevents getting caught in endeless loop. ]
:retry
 Del /Q "%TEMP%\%~n0_validate.~tmp" 2> nul
 If !Exit.Code! GTR 5 (
  Echo/===============================================================================================================
  Echo/*******************************    ^^! Attempt limit exceeded. Input rejected ^^!   *******************************
     Echo/*******************************             ^^! pipes not supported ^^!             *******************************
  Set "Exit.Code=3" & Goto :Usage
 )
 Set "rVar="
 If "%~2" == "" GOTO :Usage
 Setlocal DISABLEdelayedExpansion & rem ::: dispay occurances of carets [^] in pattern
 Endlocal & Set "Pattern=%~2"
 Set /P "rVar=Input Format for %1:!LF!!Pattern!!LF!!LF!Enter %1: "
 >"%TEMP%\%~n0_validate.~tmp" (Echo/!rVar!)
rem ::: ! important notes on usage ! ********************************************************
rem :::   /x\  [ not suited for use with pipes due to forced loop for failed matches ]
rem :::  x ! x [ test your regex pattern to ensure it is valid for the required input
rem :::   \x/    format to prevent your user/s being stuck in a goto loop.
rem :::          Error output for invalid search patterns is not displayed. ]
rem ::: *************************************************************************************
 If /I "%~3" == "/C" (
  TYPE "%TEMP%\%~n0_validate.~tmp"| findstr.exe /BRC:"%~2" > nul || (Set /A "Exit.Code+=1" & <nul Set /P"= ^! Invalid value.!LF!" & Goto :Retry)
 ) Else TYPE "%TEMP%\%~n0_validate.~tmp"| findstr.exe /XR "^%~2$" >nul || (Set /A "Exit.Code+=1" & <nul Set /P"=- ^! Invalid value.!LF!" & Goto :Retry)
 ENDLOCAL & Set "%~1=%rVar%"
 Del /Q "%TEMP%\%~n0_validate.~tmp"
 Exit /B 0
:Usage
 Set "Fi=0"
 If "!Exit.Code!" == "0" (Set "Exit.Code=1")
 >"%TEMP%\%~n0_validate.~tmp" Findstr.exe /?
  Echo//===============================================================================================================
 Echo/^| %~0 Version: 2.1 ::: Author: T3RRY ::: Release: October 2020
 Echo/^|---------------------------------------------------------------------------------------------------------------
 Echo/^| USAGE: Call %~0 [ReturnVar] ["findstr search pattern"] [Optional:"/C" -required for patterns with spaces]
 Echo/^|===============================================================================================================
 Echo/^| Examples [ Description is replaced with Arg 1-ReturnVar ]:
 Echo/^|
 Echo/^|    Call %~0 4-Digit-Number "[0-9][0-9][0-9][0-9]"
 Echo/^|    Call %~0 Alphanumeric-String "[0-9a-zA-Z]*"
 Echo/^|    Call %~0 Fixed-Length-4-digit-AlphanumericString "[0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z]"
 Echo/^|    Call %~0 AlphaString-with-3-Digit-Numeric-suffix "[a-zA-Z]*[0-9][0-9][0-9]"
 Echo/^|    Call %~0 list-of-words "[a-zA-Z ]*" /C
 Echo/^|    Call %~0 pair-of-numbers "[0-9]*[ ][0-9]*" /C
 Echo/^|
 Echo/^|      /x\    Limit of 15 character class expressions applies
 Echo/^|     x ^^! x   Case sensitive classes should use actual letters as [STRING] instead of range [A-Z]
 Echo/^|      \x/    See: https://stackoverflow.com/a/20159191/12343998

 Echo/^|                                                     -Note: %~0 does not support Input from pipes.
 Echo/^|--------------------------------------------------------------------------------------------------------------
rem [* Display findstr expression usage for users of windows with english as default language *]
 For /F "UsebackQ Delims=" %%G in ("%TEMP%\%~n0_validate.~tmp")Do (
  Set "Fi.L=%%G"
  If /I "!Fi.L:~,7!" == "Regular" Set "Fi=1"
  If "!Fi!" == "1" Echo/^|  !Fi.L!
 ) 2> Nul
 If "!Fi!" == "1" (
  Echo/^|  https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr
  Echo/^|  recommended reference: https://stackoverflow.com/questions/8844868/
 )
rem [* Display full findstr usage for users of non-english systems *]
 If "!Fi!" == "0" Findstr /?
 Echo/\================================================================================================================
 Del /Q "%TEMP%\%~n0_validate.~tmp" 2> nul
ENDLOCAL & exit /B %Exit.Code%
rem ::: [ ------------------------------------------------------------------------------------------------- End GetIn ]

:UpdateWO
rem [ read line 1 ; output to ~tmp ; append WO ; append lines 3 onward  ]
 <"!file!" set /p "line1="
 >"!file!.~tmp" Echo/!line1!
 >>"!file!.~tmp" echo/!#WO!
 <"!file!" >>"!file!.~tmp" more +2
 move /y "!file!.~tmp" "!file!"
Exit /B %errorlevel%
:UpdateSER
rem [ read lines 1-3 ; output to ~tmp with #Ser ; Append all Serial numbers from source found after #SER encountered ]
rem [ presence of #SER in source file must be validated prior to calling UpdateSer ]
 <"!File!" (
  Set /P "Line[1]="
  Set /P "Line[2]="
  Set /P "Line[3]="
 )
 >"!File!.~tmp" (
  Echo/!Line[1]!
  Echo/!Line[2]!
  Echo/!Line[3]!
  Echo/!#SER!
 )
 Set "Start=F"
 (For /F "UsebackQ Skip=3 Delims=" %%G in ("!File!")Do If /I not "%%~G" == "!#SER!" (If "!Start!" == "T" (Echo/%%~G))Else Set "Start=T") >>"%File%.~tmp"
 move /y "!file!.~tmp" "!file!"
Exit /B %errorlevel%
rem ::: [ --------------------------------------------------------------------------------------------- End Functions ]
rem ::: [ -------------------------------------------------------------------------------------- Commence Script Body ]
:Main
 Set "Menu=Echo/[R]epeat [C]ontinue [E]xit&For /F "Delims=" %%G in ('Choice /N /C:RCE')Do If "%%G"=="R" ( Goto :lbl )Else If "%%G"=="E" (Endlocal & Exit /B 0)"
SETLOCAL EnableDelayedExpansion
:WorkOrder
 set "file=Sensor Serialization.txt"
 Call :GetIn #WO "[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"
 If not "!errorlevel!" == "0" (Echo/Error: !Errorlevel! in Workorder & Endlocal & Exit /B %Errorlevel%)
 rem /* Call function to update workorder # in file */
 Call :UpdateWO
 %menu:lbl=WorkOrder%
:Serial
 Call :GetIn #SER "[0-2][0-6][ABCDEFG][0-1][0-6]"
 If not "!errorlevel!" == "0" (
  Echo/Error: !Errorlevel! in Serial & Endlocal & Exit /B %Errorlevel%
 )
rem ::: [ test presense of entered #SER number in !File! - loop for new input on fail ]
 Set "SerTF=0"
 Type "!File!" | findstr.exe /BLC:"!#SER!" && Set "SerTF=1"
 If "!SerTF!" == "0" (
  Echo/!#SER! is not present in !File!. Available:
  Type "!File!" | ( findstr.exe /XR "^[0-2][0-6][ABCDEFG][0-1][0-6]$" 2> Nul )
  Goto :Serial
 ) Else Echo confirmed
 Call :UpdateSer
 %menu:lbl=Serial%
rem /* Additions to your script should occur before this Endlocal */
rem /* reference for regular expression usage to restrict input */
 Call :GetIn -help
ENDLOCAL

Post Reply