How do I extract everything between incno and the space ie12345678 in the example batch below and put it into a incno variable?
#echo off
Set mystring=test incno12345678 wo5555 locFred Street
Echo "my string=%mystring%"
Echo incno
Echo wo
Echo loc
The incno can be 8 to 11 digits long but will always be between incno and a space in the string
I am now having trouble assigning the %%d variable to the mystring variable now it is in a for loop. Can anyone help me with this? See Below.
#echo off
SETLOCAL enableDelayedExpansion
color 0B
For /d %%d in ("C:\Users\%Username%\LocalData\*") do (
Echo "Folder = %%d"
Set mystring=%%d
echo "MyString = %mystring%"
pause
REM delete until (including) "incno":
set mystring=%mystring:*incno=%
echo %mystring%
REM delete starting with (including) " ":
set mystring=%mystring: =&rem %
echo "Incident Number = %mystring%"
pause
)
you can do it with substring replacement in two steps:
Set mystring=test incno12345678 wo5555 locFred Street
echo %mystring%
REM delete until (including) "incno":
set mystring=%mystring:*incno=%
echo %mystring%
REM delete starting with (including) " ":
set mystring=%mystring: =&rem %
echo %mystring%
set "mystring=test incno12345678 wo5555 locFred Street"
for /f %%V in ("%mystring:* incno=%") do set "incno=%%V"
Delayed expansion can be used if there is a chance that mystring might contain poison characters plus quotes:
setlocal enableDelayedExpansion
set mystring=test incno12345678 wo5555 loc"4th & Main"
for /f %%V in ("!mystring:* incno=!") do set "incno=%%V"
If the resultant value might contain ! (not an issue in this case) then delayed expansion must be toggled
setlocal disableDelayedExpansion
set mystring=test varABC!XYZ "&)^|<>"
setlocal enableDelayedExpansion
for /f %%V in ("!mystring:* var=!") do (
endlocal
set "var=%%V"
)
Related
I am trying to count all the letters that are in a sentence and I am trying to echo it on screen, but I couldn't get it to work I have tried to set a count so it goes up by 1 for each letter but couldn't get it to work. This is my code:
#echo off
:loop
SET Input=
set /p Input=jouwscript
IF "%Input%"=="" (
echo Write atleast 1 word
goto loop
) else (
FOR %%a IN (%Input%) DO (
ECHO %%a
)
)
If you are willing to accept a temporary file, it gets very simple:
Just write the string without spaces to a file and get the file size:
#Echo off
setlocal
set /p "input=Enter sentence: "
<nul >temp set /p "=%input: =%"
for %%a in (temp) do echo "%input%" has %%~za letters.
This counts all characters but spaces (also TABs, numbers, punctuation marks, and even poison chars (like <>&|%"!))
If you are on a supported Windows system and are able to use the programs already on it, you could easily do this using a single PowerShell command. This command will replace whitespace (space and tab), then calculate the length of the resulting string.
SET "Input=now is the time"
FOR /F %%A IN ('powershell -NoLogo -NoProfile -Command ^
"('%Input%' -replace '\s+','').Length"') DO (SET /A "COUNT=%%A")
ECHO COUNT is %COUNT%
Here is a method that counts characters and words input. Word length maximum of 30 characters assumed. The basis is substring modification with regards to counting letters - iterating over a given number of character spaces and incrementing the letter count for each non empty letter space.
Substring modification is also used to handle the presence of ! within strings. If you need to count letters only, ignoring characters, you will need to adjust the below to remove non letter characters from the string prior to commencing the nested loop that performs the counts. Alternately, Use findstr to reject any input that contains non letter/ whitespace characters.
#Echo off
Call :Getinput Sentence
Echo(Your Sentence: "%Sentence%"
Echo(Contains: %WC% Words and %LC% Letters
Goto :Eof
:GetInput
:# Disable DE Environment to allow substitution of ! Expansion character
Setlocal DISABLEDELAYEDEXPANSION
:# Nul Letter and Word Count Variables
Set /A "LC=WC=0"
:# Nul existing variable value
Set "input="
:# Additional safegaurd; Doublequote input command.
Set /P "input=Enter Sentence: "
:# Flag input as not entered if true; exit function
If Not Defined Input Exit /B 1
:# Substitute exclamations for counting during DelayedExpansion Environment
Set "input=%input:!=[EXC]%"
:# Allow safe use of input strings, And expansion of current value of variables when modified in code blocks:
Setlocal EnableDelayedExpansion
:# Assign Word Value; Modify ! Expansion Char for counting; Count each Character in Word
For %%W in (!Input!)Do (
Set "Word=%%W"
Set "Word=!Word:[EXC]=#!"
Set /A WC+=1
For /L %%L in (0 1 30)Do If Not "!Word:~%%L,1!" == "" (
Set /A LC+=1
)
)
:# Exit DelayedExpansion Environments
For %%i in (1 2)Do Endlocal & (
Set "LC=%LC%"
Set "WC=%WC%"
Set "Input=%Input%"
)
:# Substitute exclamation marks back into the input string after exiting DE environment
:# Assign value to Arg 1
Set "%~1=%Input:[EXC]=!%"
:# Flag input as entered
Exit /B 0
output:
C:\Users\tcdou>tout
Enter Sentence: test! one
Your Sentence: "test! one"
Contains: 2 Words and 8 Letters
C:\Users\tcdou>tout
Enter Sentence: test! ! two
Your Sentence: "test! ! two"
Contains: 3 Words and 9 Letters
C:\Users\tcdou>
As you have not stipulated exactly what you're looking to do, or exactly how you'd like your output, here's something a little bit different to the other current answers:
#Echo Off & SetLocal EnableExtensions DisableDelayedExpansion
Set "input=" & Set /P "input=jouwscript>" & If Not Defined input GoTo :EOF
For /F Delims^=^ EOL^= %%G In ('(%%SystemRoot%%\System32\cmd.exe /V /U /S /D /C
"Set /P "^=!input: ^=!" 0<NUL"^) ^| %%SystemRoot%%\System32\find.exe /N /V ""'
) Do Set /P "=%%G" 0<NUL & Echo(
Pause
The last line is optional, I've included it only for testing by GUI, (doubleclick).
As an extension of the above idea, you could of course capture each character as a variable too:
#Echo Off & SetLocal EnableExtensions DisableDelayedExpansion
(For /F "Delims==" %%G In ('"(Set Char[) 2>NUL"') Do Set "%%G=") & Set "i=0"
Set "input=" & Set /P "input=jouwscript>" & If Not Defined input GoTo :EOF
For /F Delims^=^ EOL^= %%G In ('(%%SystemRoot%%\System32\cmd.exe /V /U /S /D /C
"Set /P "^=!input: ^=!" 0<NUL"^) ^| %%SystemRoot%%\System32\find.exe /V ""'
) Do (Set "Char[0]= %%G" & For /F "Tokens=2 Delims= " %%H In ('Set Char[0]'
) Do Set /A i+=1 & SetLocal EnableDelayedExpansion & For %%I In (!i!
) Do EndLocal & Set "Char[%%I]=%%H" & Set "Char[0]=")
Echo There were %i% non space characters.
If Defined Char[1] For /L %%G In (1,1,%i%) Do Set Char[%%G]
Pause
Once again, the last line is optional, I've included it only for testing by GUI, (doubleclick).
I have been given this txt file ej:
-state;of;product-;-201705-;-ID1-;-SOLD-;-4-;-PROD;1-;;
and i need to change it to:
-state of product-;-201705-;-ID1-;-SOLD-;-4-;-PROD 1-;;
As you can see every two - I need to change ; with an space.
Can you help me?
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (YOURFILENAME.TXT) do (
SET s=%%a
SET s=!s:;= !
SET s=!s:- =-;;!
SET s=!s: -=-!
SET s=!s:-;;-=-;-!
echo !s!
)
will echo -state of product-;-201705-;-ID1-;-SOLD-;-4-;-PROD 1-;;
if you want to write each modified line back to a file, then just echo it to file.
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (YOURFILENAME.TXT) do (
SET s=%%a
SET s=!s:;= !
SET s=!s:- =-;;!
SET s=!s: -=-!
SET s=!s:-;;-=-;-!
echo !s!
) >> NewFile.txt
You need to copy the above script, paste in txtfile then rename the file as mybatch.cmd or mybatch.bat Change the MYFILENAME.TXT in the script to the name of your txt file where the lines -state;of;product-;-201705-;-ID1-;-SOLD-;-4-;-PROD;1-;; place the mybatch in the same directory as this file. double click the mybatch file. Once it is done, there will be a file called NewFile.txt which will contain the edited text.
Ok, forget about the above for now. on your PC open cmd.exe then copy everything below and then right click and paste into cmd.exe window. It will create a file for you in economic_changes called MyBatch.cmd double click and wait for it to finish. Now see file New_economic_changes.txt in the directory.
echo #echo off > "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo setlocal enabledelayedexpansion >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo for /f "delims=" %%a in (economic_changes.txt) do ( >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo SET s=%%a >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo SET s=!s:;= ! >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo SET s=!s:- =-;;! >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo SET s=!s: -=-! >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo SET s=!s:-;;-=-;-! >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo echo !s! >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
echo ) >> "%userprofile%\desktop\Economic_Folder\New_economic_changes.txt" >> "%userprofile%\desktop\Economic_Folder\MyBatch.cmd"
pause
What about this?
#echo off
setlocal EnableDelayedExpansion
set "STRING=-state;of;product-;-201705-;-ID1-;-SOLD-;-4-;-PROD;1-;;"
echo original: !STRING!
rem // Replace every `-` by `"`, enclose whole string in `""`:
set ^"STRING="!STRING:-="!"" & rem/ odd number of " deranges syntax highlighting!
rem /* Let a `for` loop dismantle the string; since `;` is a token separator
rem (like ` `, `,`, `=`), the loop divides the string at that characters;
rem every token separator that appears in a pair of `""` is maintained;
rem the string portions are reassembled, separated by spaces: */
set "RETURN= "
for %%I in (!STRING!) do set "RETURN=!RETURN!%%I "
rem // Remove surrounding `""` as well as leading and trailing space:
set "RETURN=!RETURN:~2,-2!"
rem // Replace every `"` by `-`:
set ^"RETURN=!RETURN:"=-!" & rem/ odd number of " deranges syntax highlighting!
echo modified: !RETURN!
endlocal
I want to count all the characters of a certain text. However in my code it only counts single string. But the requirement needs to count all characters including whites spaces and new line.. For example:
Hello World!
How are you today?
Hope you are okay
How am i going to do that in my code?Thanks.
My code:
#ECHO OFF
for %%i in (y.txt) do #set count=%%~zi
REM Set "string" variable
SET string=(Hello World
How are you today?
Im fine..) // i want to read these string because my code only read single string
REM Set the value of temporary variable to the value of "string" variable
SET temp_str=%string%
REM Initialize counter
SET str_len=0
:loop
if defined temp_str (
REM Remove the first character from the temporary string variable and increment
REM counter by 1. Countinue to loop until the value of temp_str is empty string.
SET temp_str=%temp_str:~1%
SET /A str_len += 1
GOTO loop
)
REM Echo the actual string value and its length.
ECHO %string% is %str_len% characters long!
this is all, you need:
#ECHO OFF
set /p "file=enter filename: "
for %%i in (%file%) do #set count=%%~zi
echo this file has %count% characters including whitespaces and special chars like line-feed/carriage-return etc.
With this function you can calculate the line number, the number of words and the number of characters in a text file
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "MOD=%1"
SET "ARC=%2"
IF %MOD%==/L GOTO :CONTLIN
IF %MOD%==/P GOTO :CONTPAL
IF %MOD%==/C GOTO :CONTCAR
:CONTLIN
FOR /f "TOKENS=*" %%z IN (%ARC%) DO SET /a LINEAS+=1
ECHO %LINEAS%
EXIT /b 0
:CONTPAL
FOR /f "TOKENS=*" %%x IN (%ARC%) DO FOR %%y IN (%%x) DO SET /a PALABRAS+=1
ECHO %PALABRAS%
EXIT /b 0
:CONTCAR
SETLOCAL
FOR /f "TOKENS=*" %%a IN (%ARC%) DO (FOR %%b IN (%%a) DO (FOR %%a IN (%%b) DO (SET
A=%%a)&(CALL :CC !A!)))
ECHO %CARACTERES%
EXIT /b 0
:CC
SET B=!A!
:I
SET /a CARACTERES+=1
SET B=%B:~1%
IF DEFINED B GOTO :I
EXIT /b 0
And I could access it from a file like this:
#ECHO OFF
SET ARCHIVO=TEXTO.TXT
FOR /F %%a IN ('CONTTEXT /L %ARCHIVO%') DO SET /a LINEAS=%%a
FOR /F %%a IN ('CONTTEXT /P %ARCHIVO%') DO SET /a PALABRAS=%%a
FOR /F %%a IN ('CONTTEXT /C %ARCHIVO%') DO SET /a CARACTERES=%%a
ECHO %LINEAS% LINEAS
ECHO %PALABRAS% PALABRAS
ECHO %CARACTERES% CARACTERES
PAUSE
In batch, how would I remove all non alphanumeric (a-z,A-Z,0-9,_) characters from a variable?
I'm pretty sure I need to use findstr and a regex.
The solutionof MC ND works, but it's really slow (Needs ~1second for the small test sample).
This is caused by the echo "!_buf!"|findstr ... construct, as for each character the pipe creates two instances of cmd.exe and starts findstr.
But this can be solved also with pure batch.
Each character is tested if it is in the map variable
:test
set "_input=Th""i\s&& is not good _maybe_???"
set "_output="
set "map=abcdefghijklmnopqrstuvwxyz 1234567890"
:loop
if not defined _input goto endLoop
for /F "delims=*~ eol=*" %%C in ("!_input:~0,1!") do (
if "!map:%%C=!" NEQ "!map!" set "_output=!_output!%%C"
)
set "_input=!_input:~1!"
goto loop
:endLoop
echo(!_output!
And it could be speed up when the goto loop is removed.
Then you need to calculate the stringLength first and iterate then with a FOR/L loop over each character.
This solution is ~6 times faster than the above method and ~40 times faster than the solution of MC ND
set "_input=Th""i\s&& is not good _maybe_!~*???"
set "_output="
set "map=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890"
%$strLen% len _input
for /L %%n in (0 1 %len%) DO (
for /F "delims=*~ eol=*" %%C in ("!_input:~%%n,1!") do (
if "!map:%%C=!" NEQ "!map!" set "_output=!_output!%%C"
)
)
exit /b
The macro $strlen can be defined with
set LF=^
::Above 2 blank lines are required - do not remove
#set ^"\n=^^^%LF%%LF%^%LF%%LF%^^":::: StrLen pResult pString
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
set "str=A!%%~2!"%\n%
set "len=0"%\n%
for /l %%A in (12,-1,0) do (%\n%
set /a "len|=1<<%%A"%\n%
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
)%\n%
for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,
EDITED - #jeb is right. This works but is really, really slow.
#echo off
setlocal enableextensions enabledelayedexpansion
set "_input=Th""i\s&& is not good _maybe_???"
set "_output="
:loop
if not defined _input goto endLoop
set "_buf=!_input:~0,1!"
set "_input=!_input:~1!"
echo "!_buf!"|findstr /i /r /c:"[a-z 0-9_]" > nul && set "_output=!_output!!_buf!"
goto loop
:endLoop
echo !_output!
endlocal
So, back to the drawing board. How to make it faster? lets try to do as less operations as we can and use as much long substring as we can. So, do it in two steps
1.- Remove all bad characters that can generate problems. To do it we will use the hability of for command to identify these chars as delimiters , and then join the rest of the sections of god characters of string
2.- Remove the rest of the bad characters, locating them in string using the valids charactes as delimiters to find substrings of bad characters, replacing then in string
So, we end with (sintax adapted to what has been answered here)
#echo off
setlocal enableextensions enabledelayedexpansion
rem Test empty string
call :doClean "" output
echo "%output%"
rem Test mixed strings
call :doClean "~~asd123#()%%%^"^!^"~~~^"""":^!!!!=asd^>^<bm_1" output
echo %output%
call :doClean "Thi\s&& is ;;;;not ^^good _maybe_!~*???" output
echo %output%
rem Test clean string
call :doClean "This is already clean" output
echo %output%
rem Test all bad string
call :doClean "*******//////\\\\\\\()()()()" output
echo "%output%"
rem Test long string
set "zz=Thi\s&& is not ^^good _maybe_!~*??? "
set "zz=TEST: %zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%%zz%"
call :doClean "%zz% TEST" output
echo %output%
rem Time long string
echo %time%
for /l %%# in (1 1 100) do call :doClean "%zz%" output
echo %time%
exit /b
rem ---------------------------------------------------------------------------
:doClean input output
setlocal enableextensions enabledelayedexpansion
set "map=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 "
set "input=%~1"
set "output="
rem Step 1 - Remove critical delimiters
(
:purgeCritical
for /L %%z in (1 1 10) do (
for /f tokens^=1^-9^,^*^ delims^=^=^"^"^~^;^,^&^*^%%^:^!^(^)^<^>^^ %%a in ("!input!") do (
set "output=!output!%%a%%b%%c%%d%%e%%f%%g%%h%%i"
set "input=%%j"
)
if not defined input goto outPurgeCritical
)
goto purgeCritical
)
:outPurgeCritical
rem Step 2 - remove any remaining special character
(
:purgeNormal
for /L %%z in (1 1 10) do (
set "pending="
for /f "tokens=1,* delims=%map%" %%a in ("!output!") do (
set "output=!output:%%a=!"
set "pending=%%b"
)
if not defined pending goto outPurgeNormal
)
goto purgeNormal
)
:outPurgeNormal
endlocal & set "%~2=%output%"
goto :EOF
Maybe not the fastest, but at least a "decent" solution
#echo eof
call :purge "~~asd123#()%%%^"^!^"~~~^:^=asd^>^<bm_1" var
echo (%var%)
goto :eof
:purge StrVar [RtnVar]
setlocal disableDelayedExpansion
set "str1=%~1"
setlocal enableDelayedExpansion
for %%a in ( - ! # # $ % ^^ ^& + \ / ^< ^> . ' [ ] { } ` ^| ^" ) do (
set "str1=!str1:%%a=!"
)
rem dealing with some delimiters
set "str1=!str1:(=!"
set "str1=!str1:)=!"
set "str1=!str1:;=!"
set "str1=!str1:,=!"
set "str1=!str1:^^=!"
set "str1=!str1:^~=!"
set "temp_str="
for %%e in (%str1%) do (
set "temp_str=!temp_str!%%e"
)
endlocal & set "str1=%temp_str%"
setlocal disableDelayedExpansion
set "str1=%str1:!=%"
set "str1=%str1::=%"
set "str1=%str1:^^~=%"
for /f "tokens=* delims=~" %%w in ("%str1%") do set "str1=%%w"
endlocal & set "str1=%str1%"
endlocal & if "%~2" neq "" (set %~2=%str1%) else echo %str1%
goto :eof
Still cannot deal with ~ and = but working on it
EDIT: = now will be cleared
EDIT: ~ now will be cleared
Okay so here is what I have.
#echo off
setLocal EnableDelayedExpansion
:begin
set /a M=0
set /a number=0
set /p Input=You:
echo %Input% >> UIS
for /F "tokens=1 delims= " %%i in ("%Input%") do (
set /a M+=1
set i!M!=%%i
)
del UIS 1>nul 2>nul
:loop
set /a number+=1
set invar=!i%number%!
echo %invar%
pause > nul
goto loop
Say, for example, the Input string was "Lol this is my input string"
I want the for loop to set i!M! where M = 1 to "Lol", where M = 2 i!M! is "this" and where M = 3 i!M! is "is" and so on. Now, of course, this can't go on forever, so even if I have to stop when M = 25 or something, and say the string was only 23 words long. Then when M = 24 and 25 then i!M! is simply null or undefined.
Any help is appreciated, thank you.
for /f reads line by line, not word by word.
Here's an answer proposed at How to split a string in a Windows batch file? and modified for your situation:
#echo off
setlocal ENABLEDELAYEDEXPANSION
REM Set a string with an arbitrary number of substrings separated by semi colons
set teststring=Lol this is my input string
set M=0
REM Do something with each substring
:stringLOOP
REM Stop when the string is empty
if "!teststring!" EQU "" goto displayloop
for /f "delims= " %%a in ("!teststring!") do set substring=%%a
set /a M+=1
set i!M!=!substring!
REM Now strip off the leading substring
:striploop
set stripchar=!teststring:~0,1!
set teststring=!teststring:~1!
if "!teststring!" EQU "" goto stringloop
if "!stripchar!" NEQ " " goto striploop
goto stringloop
:displayloop
set /a number+=1
set invar=!i%number%!
echo %invar%
pause > nul
goto displayloop
endlocal
for /F command divide a line in a definite number of tokens that must be processed at once via different replaceable parameters (%%i, %%j, etc). Plain for command divide a line in an undefined number of words (separated by space, comma, semicolon or equal-sign) that are processed one by one in an iterative loop. This way, you just need to change this for:
for /F "tokens=1 delims= " %%i in ("%Input%") do (
by this one:
for %%i in (%Input%) do (
PS - I suggest you to write the array in the standard form, enclosing the subscript in square brackets; it is clearer this way:
set i[!M!]=%%i
or
set invar=!i[%number%]!