I'm trying to recuperate a particular data from a file (we will call it MyFile.dart) using a batch file.
To be more precise I'm trying to recuperate the 2.4 from this line :
static var version = 2.4;
First, I use a for loop to iterate through each line of my file :
FOR /F "tokens=*" %%i IN (MyFile.dart)
Then I want to check if the line contains a particulare string (here "var version")
set str = %%i
if not %str:"var version"=% == %str% DO
I got this from this topic but here I get the error :
=str is unexpected
Since the check doesn't work, I comment it and I try my next for loop on each line of MyFile.dart (if the check worked it would have been only on the line containing "var version") :
set str = %%i
FOR /F "tokens=2 delims==" %%a IN (%str%) DO (
#echo %%a
)
Here I'm supposed to split the line using "=" as a separator and display the second element of the split array, but I get nothing printed in the console, and when I comment #echo off, I see that %str% is null. I tried using directly %%i but I also get an error.
So I hardcoded the line I'm interested in the loop :
set str = %%i
FOR /F "tokens=2 delims==" %%a IN ("static var version = 2.4;") DO (
#echo %%a
)
And got the expected result of 2.4; in the console (but obviously it's not how I want to get it).
So to summarize :
First problem : the "if not" to check if the line contains a particular substring doesn't work.
Second problem : I can't pass the variable from the first loop (a line of the file) to the second loop to then parse it.
Here is my whole code :
FOR /F "tokens=*" %%i IN (MyFile.dart) DO (
set str = %%i
if not %str:"var version"=% == %str% DO (
FOR /F "tokens=2 delims==" %%a IN (%str%) DO (
#echo %%a
)
)
)
NB : If you have a totally different algorithm to get to the same result I will take it !
set str = %%i
This sets the variable "strSpace" to the value "Space(the value of %%i)"
Use the syntax
set "str=%%i"
Including the quotes. Use set "var1=value" for setting STRING values - this avoids problems caused by trailing spaces. Quotes are not needed for setting arithmetic values (set /a`)
if not %str:"var version"=% == %str% DO (
The correct syntax is
if not "%str:var version=%" == "%str%" (
or, better
if "%str:var version=%" neq "%str%" (
The comparison is literal - both sides of the comparison operator must be quoted since the value may contain separators like spaces.
The correct syntax for string substitution is %varname:string=substitutestring%
Why set str again?
To parse a string using = as a delimiter, use
FOR /F "tokens=2 delims==" %%a IN ("string") DO (
Note however that %str% will be the value str had at the time the outer loop (%%i) was encountered. For an explanation of how this works, see Stephan's DELAYEDEXPANSION link
You should consider using
FOR /F "tokens=2 delims==" %%a IN ("%%i") DO (
This worked for me - I changed the name of the file
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=*" %%i IN (q71930885.txt) DO (
set "str=%%i"
if "!str:var version=!" neq "!str!" (
FOR /F "tokens=2 delims==" %%a IN ("%%i") DO ( #echo %%a )
)
)
GOTO :EOF
Response:
Space2.4;
Related
This is my code:
for /f "usebackq tokens=1-3 delims=," %%a in ("%my_path%") do (
set z=%%a
for %%A in (!z:.= !) do (
echo %%A
)
)
In the second loop I need to get list from !z:.= !. But it doesn't work. However, if I do this way:
for /f "usebackq tokens=1-3 delims=," %%a in ("%my_path%") do (
set z=%%a
for %%A in ("!z:.= !") do (
echo %%A
)
)
Then it works, but I have two extra " in output which I don't need. Could anyone say how to get list from !z:.= ! in a correct way (without getting extra quotes)?
EDIT: In pseudo code in the second loop I need:
string[] splits = z.split(".");
for (var split : splits) {
echo split
}
I have a tab delimited txt file and I am trying to find the value 0 in the last column in every line then rename that value from 0 to K.This is the code I have come up with so far but I can't get the values to change. What am I doing wrong here?
ECHO ON
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=E:\psexport"
SET "destdir=E:\psexport"
SET "filename1=%sourcedir%\nk3.txt"
SET "outfile=%destdir%\nk4.txt"
(
FOR /f * IN ("%filename1%") DO (
SET "line=*"
SET "line=!line:0=K"
ECHO !line!
)
)>"%outfile%"
GOTO :EOF
`
You are using bang where I would expect to see percentage. Also, I'm not sure about that second set statement.
See my code example below. In the echo command I am calling line, with the variable substitution of replace 0 with K. It's wrapped in percentages because that whole expression is the variable we want to echo.
ECHO ON
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=E:\psexport"
SET "destdir=E:\psexport"
SET "filename1=%sourcedir%\nk3.txt"
SET "outfile=%destdir%\nk4.txt"
(
FOR /f * IN ("%filename1%") DO (
SET "line=*"
ECHO %line:0=K%
)
)>"%outfile%"
GOTO :EOF
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=E:\psexport"
SET "destdir=E:\psexport"
SET "filename1=%sourcedir%\nk3.txt"
SET "outfile=%destdir%\nk4.txt"
(
FOR /f "usebackq delims=" %%a IN ("%filename1%") DO (
SET "line=%%a"
IF "!line:~-2!"==" 0" (
ECHO !line:~0,-2! K
) ELSE (
ECHO %%a
)
)
)>"%outfile%"
GOTO :EOF
The for syntax requires a metavariable - I've used %%a - which is alphabetical and case-sensitive.
The modifier usebackq is used because the name of the file being read is quoted.
delims= means no delimiters, so the entire file line is delivered to %%a.
To use substringing, we need to transfer the value to a standard environment variable, then test that the last two characters of the line read are 0 so that 10 does not get modified. If the test is true, echo the line from the beginning (character 0) through to the end - 2 characters and append K, otherwise, regurgitate the original line.
The set syntax you were using replaces every 0 with K.
I want to create a script that sets specific values, then writes each value into a new line of a text document. After that it should read the document and set new values to a specified line of the text document, then echo those out.
I have tried different values for "skip=#" which didn't change anything. When I tried to not use the "skip=0" option in the first FOR and that makes the batch echo out "Value three" for all values. (Quick edit: I've used this website for information on it so far.)
#ECHO OFF
REM Setting values
SET #valueone=Value one
SET #valuetwo=Value two
SET #valuethree=Value three
REM Saving values
IF EXIST "values.txt" DEL "values.txt"
echo %#valueone% >values.txt
echo %#valuetwo% >>values.txt
echo %#valuethree% >>values.txt
REM Reading values again and echoing them at at the same time.
REM This was separated (first reading then echoing) but it didn't change anything.
FOR /F "skip=0 delims=" %%i IN (values.txt) DO SET #valueonefinal=%%i
echo Value number one:
echo %#valueonefinal%
echo.
FOR /F "skip=1 delims=" %%i IN (values.txt) DO SET #valuetwofinal=%%i
echo Value number two:
echo %#valuetwofinal%
echo.
FOR /F "skip=2 delims=" %%i IN (values.txt) DO SET #valuethreefinal=%%i
echo Value number three:
echo %#valuethreefinal%
pause
Expected output in the console:
Value number one:
Value one
Value number two:
Value two
Value number three:
Value three
Actual output:
delims=" was unexpected at this time.
Value number one:
ECHO is off.
Value number two:
Value three
Value number three:
Value three
I'm not that experienced but I suspect that I may be doing the "skip=#" part wrong. Any help with this is greatly apprechiated!
The option skip=0 is not accepted by the for /F command, the specified number must be in the range from 1 to 231 − 1. To skip no lines just do not provide the skip option at all.
You seem to try to assign the text of a certain line to a variable (for instance, the third one):
FOR /F "skip=2 delims=" %%i IN (values.txt) DO SET #valuethreefinal=%%i
Well, this actually assigns the content of the last line to the variable, because the set command in the body of the loop is executed for all but the skipped lines. More precisely said, the for /F loop iterates over all non-empty lines which do not begin with ; which is the default character of the eol option.
To actually assign the third line to the variable you need to change the code:
rem // Ensure that the variable is initially unset somewhere before:
set "#valuethreefinal="
rem // As soon as the variable is set the `if` condition is no longer going to be fulfilled:
for /F "usebackq skip=2 delims=" %%i in ("values.txt") do if not defined #valuethreefinal set "#valuethreefinal=%%i"
This does not necessarily assign the third line to the variable, it actually assigns the text of the first line after the (two) skipped ones that is not empty and does not begin with ; (remember the eol character).
The usebackq option allows to put quotation marks around the file name. This is not necessary in your situation, but it is when a file name contains SPACEs or other special characters.
I used the undocumented quoted set syntax here because this is safer than the unquoted one, particularly when it comes to special characters and also to avoid unintended trailing white-spaces.
To disable the eol character you could use the undocumented unquoted option string syntax:
for /F usebackq^ skip^=2^ delims^=^ eol^= %%i in ("values.txt") do if not defined #valuethreefinal set "#valuethreefinal=%%i"
As you can see the SPACEs and =-signs are escaped by the caret symbol ^ in order to treat the whole option string as a unit.
This still skips over empty lines though. To prevent this take a loop at this thread: preserve empty lines in a text file while using batch for /f.
Since you want to capture more than a single line you could extend the code to the following:
set "#valueonefinal=" & set "#valuethreefinal=" & set "#valuethreefinal="
for /F usebackq^ delims^=^ eol^= %%i in ("values.txt") do (
if not defined #valueonefinal (
set "#valueonefinal=%%i"
) else (
if not defined #valuetwofinal (
set "#valuetwofinal=%%i"
) else (
if not defined #valuethreefinal (
set "#valuethreefinal=%%i"
)
)
)
)
This can be compressed to:
set "#valueonefinal=" & set "#valuethreefinal=" & set "#valuethreefinal="
for /F usebackq^ delims^=^ eol^= %%i in ("values.txt") do (
if not defined #valueonefinal (
set "#valueonefinal=%%i"
) else if not defined #valuetwofinal (
set "#valuetwofinal=%%i"
) else if not defined #valuethreefinal (
set "#valuethreefinal=%%i"
)
)
A more flexible method is to use pseudo-arrays:
rem // Initialise an index counter:
set /A "INDEX=0"
rem // Assign every line to an element of a pseudo-array:
for /F usebackq^ delims^=^ eol^= %%i in ("values.txt") do (
rem // Increment the index counter:
set /A "INDEX+=1"
rem // Assign the current line to a pseudo-array element:
call set "#valuefinal[%%INDEX%%]=%%i"
)
The (non-empty) lines of the file value.txt are now assigned to variables called #valuefinal[1], #valuefinal[2], #valuefinal[3], etc. (there is no concept of arrays in batch scripting, the variables are exactly the same as yours, #valueonefinal, etc., that is why I use the term "pseudo").
The call command is used here in order to be able to write and read the variable INDEX within the same block of code; just using set "#valuefinal[%INDEX%]=%%i" would result in assigning and therefore overwriting the variable #valuefinal[0] in every loop iteration.
Your problem is that you are parsing the File from Top to bottom, and skipping the First value, what you don't realize is that FOR will set the value to the LAST item it found. This means that the script as written can only ever return the last item in the values file.
To deal with this you could:
Break the loop on the first match and return that result.
Remove values as they are matched
I like to Break the loop.
First let me make you code a little more streamlined so we can re-write it multiple times to show each
This is going to work exactly as your existing code but now we can easily add more values and loop them in a quick go.
Your Original Code Refactored:
#( SETLOCAL EnableDelayedExpansion
ECHO OFF
SET "_ValuesFile=%~dp0values.txt"
REM Remove Old Values File
DEL /F /Q "!_ValuesFile!" >NUL 2>NUL
REM Saving values
FOR %%A IN (one two three) DO (
ECHO.Value %%A>>"!_ValuesFile!" )
)
CALL :Main
( PAUSE
ENDLOCAL
EXIT /B 0
)
:Main
FOR /L %%L IN (0,1,2) DO (
CALL SET /A "_Value=%%L + 1"
ECHO.&ECHO.------ Iteration: %%L ------&ECHO.Value number !_Value!:
IF %%L EQU 0 ( SET "_ForOptions=tokens=*" ) ELSE (
SET "_ForOptions=Skip=%%L tokens=*" )
CALL :Loop %%L
)
GOTO :EOF
:Loop
FOR /F "%_ForOptions%" %%i IN (' type "%_ValuesFile%"
') DO ( CALL SET "#value%_Value%final=%%i" )
ECHO.!#value%_Value%final!
GOTO :EOF
* Break the Loop on the First Match:
#( SETLOCAL EnableDelayedExpansion
ECHO OFF
SET "_ValuesFile=%~dp0values.txt"
REM Remove Old Values File
DEL /F /Q "!_ValuesFile!" >NUL 2>NUL
REM Saving values
FOR %%A IN (one two three) DO (
ECHO.Value %%A>>"!_ValuesFile!" )
)
CALL :Main
( PAUSE
ENDLOCAL
EXIT /B 0
)
:Main
FOR /L %%L IN (0,1,2) DO (
CALL SET /A "_Value=%%L + 1"
ECHO.&ECHO.------ Iteration: %%L ------&ECHO.Value number !_Value!:
IF %%L EQU 0 ( SET "_ForOptions=tokens=*" ) ELSE (
SET "_ForOptions=Skip=%%L tokens=*" )
CALL :Loop %%L
)
ECHO.&ECHO.------ Final Values After %%L Iterations: ------
SET #value
GOTO :EOF
:Loop
FOR /F "Tokens=*" %%A IN ('
CMD /C "FOR /F %_ForOptions% %%i IN (' type "%_ValuesFile%" ') DO #(ECHO.%%i&exit /b)"
') DO #(
SET "#value%_Value%final=%%~A"
)
ECHO.!#value%_Value%final!
GOTO :EOF
Example Output from Break the Loop Version:
Y:\>C:\Admin\S-O_Value-Checker_v2.cmd
------ Iteration: 0 ------
Value number 1:
Value one
------ Iteration: 1 ------
Value number 2:
Value two
------ Iteration: 2 ------
Value number 3:
Value three
------ Final Values After %L Iterations: ------
#value1final=Value one
#value2final=Value two
#value3final=Value three
Press any key to continue . . .
Script stores the lines along with line numbers where ever "firstword" is found, those line numbers are retrieved from temp_onsetTime.txt. trying to retrieve the 4th line from that line number and write it in another file.
line set var=%%g% set /a var=%var% + 4 , string var is not getting converted into integer.
cls
break>ontset_time.txt
break>temp_ontsetTime.txt
set firstword="stimuli\1200.wav"
set secondword="MainScreen.OnsetTime"
findstr /l /I /n %firstword% "C:\Users\BHAVYA\Desktop\AudOdd.txt">>temp_ontsetTime.txt
for /F " delims=: tokens=1 " %%g in ( C:\Users\BHAVYA\Desktop\temp_ontsetTime.txt ) do (
echo %%g
echo.
set var=%%g%
set /a var=%var% + 4
echo %var%
for /F " delims=: tokens=1,2 skip= %var%" %%h IN ( ' findstr /l /I %secondword% "C:\Users\BHAVYA\Desktop\AudOdd.txt" ' ) do (
echo %%h %%i
echo %%i%>>ontset_time.txt
goto loop_end
)
:loop_end
echo loop ended
)
pause
Problem 1: set var=%%g% is incorrect; set var=%%g is closer (%%g accesses the metavariable %%g); set /a var=%%g is better still (since %%g is apparently an integer).
Problem2: You need to learn about delayed expansion - there are hundreds of references here on SO. Batch replaces every %var% with its value as it stands when the for loop is parsed - not when it is executed, hence
set /a = var + 4
will increase the value of var by 4 - you then need to use
call echo %%var%%
to access the changed value of var if you are not using delayed expansion.
AAMOI, this is equivalent to
set /a var=%%g+4
Third problem - still the delayedexpansion problem - %var% will be replaced by its value at the time for...%%g... was parsed, not the value as modified within the loop.
Fourth problem : labels are not allowed within a block statement (a parenthesised series of statements).
Here's a cure without delayed expansion
for /F " delims=: tokens=1 " %%g in ( C:\Users\BHAVYA\Desktop\temp_ontsetTime.txt ) do (
echo %%g
echo.
set /a var=%%g + 4
call echo %%var%%
for /f "tokens=1,2delims==" %%m in ('set var') do if /i "%%m"=="var" (
echo var is %%n
set "show=Y"
for /F " delims=: tokens=1,2 skip=%%n" %%h IN ( ' findstr /l /I %secondword% "C:\Users\BHAVYA\Desktop\AudOdd.txt" ' ) do if defined show (
echo %%h %%i
set "show="
echo %%i%>>ontset_time.txt
)
)
echo loop ended
)
Note here that using set var will list the current environment values that begin var in the format var=99. We tokenise that on = and the first token (%%m) must be var, not var1 or anything else. If it is, its value is in %%n, so set the flag show to a value (any value will do) and then process the file. On the first "hit", clear the value in show- it is now undefined, so no more processing takes place until the next outer loop starts.
[I obviously can't test this]
I want to write a batch script which reads each line of a file. Sounds easy but the problem is that not every line has the same amount of tokens. The next thing is that every token is seperated from each other with a delimiter which I don't want to have in my output.
Here is a example of the file:
string1|string2|string3|string4
string1|||string4
When I'm reading that file, every token has to be on its right place. What I mean is when I'm reading the second line the output must be:
string1 empty empty string4
thanks for help
gawk for Windows can do the job:
awk -F"|" "{for (i=1;i<=NF;i++) $i=$i?$i:\"empty\"};7" file.in>file.out
#ECHO OFF
SETLOCAL
(
FOR /f "delims=" %%a IN (q21551753.txt) DO (
SET line=%%a
SETLOCAL ENABLEDELAYEDEXPANSION
SET line=!line:^|= ^|!
ECHO(!line!
endlocal
)
)>tempfile.txt
SET "spaces= "
FOR /f "tokens=1-7delims=|" %%a IN (tempfile.txt) DO (
SET "$a=%%a%spaces%"
SET "$b=%%b%spaces%"
SET "$c=%%c%spaces%"
SET "$d=%%d%spaces%"
SET "$e=%%e%spaces%"
SET "$f=%%f%spaces%"
SET "$g=%%g%spaces%"
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO(!$a:~0,8!!$b:~0,9!!$c:~0,8!!$d:~0,8!!$e:~0,9!!$f:~0,5!!$g:~0,6!
endlocal
)
GOTO :EOF
I used a file named q21551753.txt for my testing.
string1|string2|string3|string4
string1|||string4
|string2||string4|string5|string6
%one%|!2!||"three"|^four^|string6
Response:
string1 string2 string3 string4
string1 string4
string2 string4 string5 strin
%one% !2! "three" ^four^ strin
Note that the column-widths are defined in the ECHO(!$a... statement - your choice of the number and width of each column. Note that spaces is set to a bunch of spaces.
tempfile.txt is created. Whether you delete this, where it is created and what you call it are all up to you.
The following assumes data does not contain !, and no line begins with ;. These restrictions can be eliminated with more code.
The key trick is to use variable expansion search and replace to convert str1|str2|str3|str4 into "str1"|"str2"|"str3"|"str4". Then a second FOR /F can safely parse the tokens, even when the value is missing. The values you want are in %%~A, %%~B, %%~C, and %%~D. The line I ECHO is just to demonstrate the values of each token.
#echo off
setlocal enableDelayedExpansion
for /f "delims=" %%L in (test.txt) do (
set "ln=%%L"
set "ln="!ln:^|="|"!""
for /f "tokens=1-4 delims=|" %%A in ("!ln!") do (
echo A=%%~A B=%%~B C=%%~C D=%%~D
)
)
Thanks for your answers.
But I found out that I had another problem. The count of the tokens are not always the same and the count is often about 20-40 tokens at one line.
I created a solution with a sub-procedure:
#echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (Book1.csv) DO (
set "work=%%a"
for /l %%i in (1,1,2) do set "work=!work:||=|NULL|!"
set "line=!work!"
call :processToken
)
goto eof
:processToken
for /F "tokens=1* delims=|" %%x in ("!line!") do (
echo %%x
set line=%%y
)
if not "!line!" == "" goto :processToken
goto :eof
:eof