Batch File to edit specific line of Text file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
T3RRY
Posts: 243
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: 42
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: 243
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: 42
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: 243
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

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

Re: Batch File to edit specific line of Text file

#36 Post by werejago » 06 Jan 2021 13:51

Problem resolved.
Last edited by werejago on 15 Jan 2021 10:21, edited 2 times in total.

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

Re: Batch File to edit specific line of Text file

#37 Post by T3RRY » 06 Jan 2021 14:08

At a quick glance, you have multiple commands within your menu macro that are not concatenated.

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

Re: Batch File to edit specific line of Text file

#38 Post by werejago » 06 Jan 2021 14:36

What do you mean? R is to retry or repeat an entry, C is to continue into the menu selection and E is to start programs and exit batch program.

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

Re: Batch File to edit specific line of Text file

#39 Post by werejago » 07 Jan 2021 07:33

Do you have any recommendations or sources where I could go to learn how to fix this issue?

Thank you

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

Re: Batch File to edit specific line of Text file

#40 Post by werejago » 07 Jan 2021 07:42

The code seems to functions perfectly fine despite not opening a "start ezcad "file.ez" in the if E end program command. If i'm not explaning myself clear enough I can try explaining again.

Code: Select all

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" (start notepad "Sensor Serialization.txt" start C:\Users\ptech\Documents\Ezcad2.14.9(20170509)\EzCad2.exe "Sensor Engraving.EZD"  Endlocal & Exit /B 0)"

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

Re: Batch File to edit specific line of Text file

#41 Post by T3RRY » 07 Jan 2021 09:44

werejago wrote:
07 Jan 2021 07:42
The code seems to functions perfectly fine despite not opening a "start ezcad "file.ez" in the if E end program command. If i'm not explaning myself clear enough I can try explaining again.

Code: Select all

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" (start notepad "Sensor Serialization.txt" start C:\Users\ptech\Documents\Ezcad2.14.9(20170509)\EzCad2.exe "Sensor Engraving.EZD"  Endlocal & Exit /B 0)"
Concatenations of commands on the same line use the & character.
In the If conditon of the final else statement there is no concatenation between the two start commands and the endlocal command.

Code: Select all

If "%%G"=="E" (start notepad "Sensor Serialization.txt" start C:\Users\ptech\Documents\Ezcad2.14.9(20170509)\EzCad2.exe "Sensor Engraving.EZD"  Endlocal & Exit /B 0)
When building macros, There's an approach for doing so that helps prevent these issues by providing better readability /maintainability.


Prior to the Macro definition, define a variable to allow definition of a multiline variable like so:

Code: Select all

(Set \n=^^^

%=Macro Newline Var. Do not Modify. =%)
Then you may define Macro's Like So:

Code: Select all

 Set Menu=For %%n in (1 2) Do if %%n==2 ( %\n%
  Echo/[R]epeat [C]ontinue [E]xit %\n%
  For /F "Delims=" %%G in ('Choice /N /C:RCE')Do ( %\n%
   If "%%G"=="R" ( Goto :lbl ) %\n%
   If "%%G"=="E" ( %\n%
    start notepad "Sensor Serialization.txt" %\n%
    start "" "C:\Users\ptech\Documents\Ezcad2.14.9(20170509)\EzCad2.exe" "Sensor Engraving.EZD"  %\n%
    Endlocal %\n%
    Exit /B 0 %\n%
 )))
For this particular case though, I don't see the value of using a macro instead of just scripting the menu in the relevant piece of code.
Macro's are far more advantageous in scenarios where there acting like functions - used repeatedly to process / output multiple and /or dynamic arguments

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

Re: Batch File to edit specific line of Text file

#42 Post by werejago » 07 Jan 2021 09:58

Terry I found my problem!

It was simply the pathing for the ezcad program.
The path includes: "C:\Users\ptech\Documents\Ezcad2.14.9(20170509)\EzCad2.exe" the "(20170509)" in the path i believe was causing the problem and crashing or ending the program.

Any suggestions for a quick fix besides renaming the file?
I may be able to get away with renaming the pathing without the (20170509) if not.

Thank you for taking the time and your feedback is highly appreciated!

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

Re: Batch File to edit specific line of Text file

#43 Post by werejago » 07 Jan 2021 10:10

Ok actually I still cannot get 2 programs to open up at the same time upon exit.

The end objective is to simply open the notepad file "sensor.txt" that was edited and the Ezcad file/program.

I can only get one or the other to open why not both?

If "%%G"=="E" (start notepad "Sensor Serialization.txt" start C:\Users\ptech\Documents\Ezcad2.14.9\EzCad2.exe "Sensor Engraving.EZD" Endlocal & Exit /B 0)

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Batch File to edit specific line of Text file

#44 Post by Squashman » 07 Jan 2021 10:13

werejago wrote:
07 Jan 2021 10:10
Ok actually I still cannot get 2 programs to open up at the same time upon exit.

The end objective is to simply open the notepad file "sensor.txt" that was edited and the Ezcad file/program.

I can only get one or the other to open why not both?

If "%%G"=="E" (start notepad "Sensor Serialization.txt" start C:\Users\ptech\Documents\Ezcad2.14.9\EzCad2.exe "Sensor Engraving.EZD" Endlocal & Exit /B 0)
As you were already told, you are not concatenating the commands together with ampersands.

Squashman
Expert
Posts: 4471
Joined: 23 Dec 2011 13:59

Re: Batch File to edit specific line of Text file

#45 Post by Squashman » 07 Jan 2021 10:14

werejago wrote:
07 Jan 2021 09:58
Terry I found my problem!

It was simply the pathing for the ezcad program.
The path includes: "C:\Users\ptech\Documents\Ezcad2.14.9(20170509)\EzCad2.exe" the "(20170509)" in the path i believe was causing the problem and crashing or ending the program.

Any suggestions for a quick fix besides renaming the file?
I may be able to get away with renaming the pathing without the (20170509) if not.

Thank you for taking the time and your feedback is highly appreciated!
Any literal uses of a closing parentheses inside of an existing parenthesized code block need to be escaped.

Post Reply