Multiple spaces in a for /f loop - batch-file

I need to separate a string based on spaces, but only after the first space. However, the second string returns only one word.
The code I'm currently using is this:
#echo off
set string=alone these are together
for /f "tokens=1 " %%g IN ("%string%") do set first=%%g
for /f "tokens=2*" %%g IN ("%string%") do set second=%%g
echo %first%
echo %second%
pause
Right now, my output is alone these, but I want alone these are together.
Am I setting the variable wrong, or is my sytax on the token option incorrect?

* is its own token in the token list, so "tokens=2*" %%g puts the second token in %string% in %%g and everything after it in %%h.
for /f "tokens=1,*" %%g IN ("%string%") do (
set "first=%%g"
set "second=%%h"
)
will put the first the first token in %first% and everything else in %second%.

Related

Separate first and last names with for loop

I'm working on a batch that creates a .txt-file from a record. The file will be processed later by another program.
The record looks like this at the moment:
11111;Lastname Firstname SecondFirstname;1234567;SomeText
22222;Lastname Firstname;1254557;SomeText
33333;Lastname Firstname;1234567;SomeText
I would like to have a semicolon between the last name and the first name. The problem is the sentences with two first names. Here should be no semicolon between the names.
In the end it should look like this:
11111;Lastname;Firstname SecondFirstname;1234567;SomeText
22222;Lastname;Firstname;1254557;SomeText
33333;Lastname;Firstname;1234567;SomeText
Does anyone have an idea here?
I have tried the following but that does not solve the problem with the two first names:
type nul>tmp.txt
for /f "delims=: tokens=1*" %%i in ('findstr /n "^" "test_output.txt"') do set "Zeile=%%j" &call :sub
move /y "tmp.txt" "test_output.txt"
goto :eof
:sub
if not defined Zeile (
>>tmp.txt echo.
goto :eof
)
>>tmp.txt echo %Zeile: =;%
goto :eof
Parsing the first time by the ; delimiter and parsing the second token (the third, if you take the line numbers into account) a second time by a <SPACE> delimiter (with tokens=1,*) solves your problem:
#echo off
(for /f "tokens=1-3,* delims=;:" %%A in ('findstr /n "^" "test_output.txt"') do (
if "%%B"=="" echo/
for /f "tokens=1,*" %%M in ("%%C") do (
echo/%%B;%%M;%%N;%%D
)
))>tmp.txt
goto :eof
(redirecting the whole output at once is a lot faster than redirecting single lines - especially with big files)
You need two nested for /F the first to split at the semicolon, the 2nd to split at the space limited to 2 splits.
Using uppercase %A and lowercase %a for the meta variables, in cmd line:
for /F "tokens=1-3* delims=;" %A in (test_output.txt) do #for /F "tokens=1*" %a in ("%B") do #Echo %A;%a;%b;%C;%D
In a batch file saving to new_output.txt:
:: Q:\Test\2019\06\04\SO_56443069.cmd
#Echo off&SetLocal EnableDelayedExpansion
(for /F "tokens=1-3* delims=;" %%A in (test_output.txt
) do for /F "tokens=1*" %%a in ("%%B"
) do Echo %%A;%%a;%%b;%%C;%%D
) >new_output.txt
Sample output:
> type new_output.txt
11111;Lastname;Firstname SecondFirstname;1234567;SomeText
22222;Lastname;Firstname;1254557;SomeText
33333;Lastname;Firstname;1234567;SomeText

Batch - Extract every word on a line to a markdown link

This is code from a call above it. I extract line 5 from a file with this code which leaves it in %%c. I then want to take each word in that line (there can be from 1 to nth words) and create a markdown link like
[word](word.html)
and append those to a txt file. This is what I have so far. If I have 10 words do I really have to add all the tokens in the command like %%d, %%e, etc.? Can I use something like tokens=1-*. * meaning the last token in the line? Using tokens=* uses the whole line of words as one token I believe.
setlocal enabledelayedexpansion
set "lineNr=5"
set /a lineNr-=1
for /f "usebackq delims=" %%c in (`more +!lineNr! "%~1"`) DO (
for /f "tokens=1-2 delims= " %%d in ("%%c") do (
echo [%%d]^(tags/%%d.html^) [%%e]^(tags/%%e.html^) ^<br^> >> index.txt
)
goto :eof
)
Here is an example of how you can do that. Note I just used some parts as an example as I do not have time to format escape characters now, but you'll get the idea :)
#echo off
set "lineNr=5"
set /a lineNr-=1
for /f "usebackq delims=" %%c in (`more +%lineNr% "%~1"`) DO set "line=%%c"
for %%i in (%line%) do echo| set /p =[%%i](tags/%%i.html)>>index.txt
OK, I got it working by doing this -
set "lineNr=5"
set /a lineNr-=1
for /f "usebackq delims=" %%c in (`more +%lineNr% "overview.md"`) DO (
set "line=%%c"
goto :next
)
:next
for %%i in (%line%) do echo| set /p =[%%i](tags/%%i.html) >> index.txt
Have to break out of the loop line listing after the first line wanted(line 5).

How to fetch second row, second column from a .csv file?

I have a CSV file that has looks something like below:
Order ID,Order Date,Ship Date,Ship Mode
CA-2011-103800,2013-01-03,2013-01-07 00:00:00,Standard Class
CA-2011-112326,2013-01-04,2013-01-08 00:00:00,Standard Class
All I need is to get from first data row the order date, i.e. 2013-01-03 in this case.
I tried the code below which doesn't solve the problem.
set file=output.csv
for /f "skip=1 tokens=2 delims=," %%A in (%file%) do (echo %%A)
I am a beginner. Can anyone help me out with this?
This can be done VERY easy by creating an array out of the data from file.csv. By using !Line[2]! we can grab any line of the .csv file we want. Simply change the Row & Column configurations to however you need. This can be very useful for searching a .csv file.
#echo off
#setlocal enabledelayedexpansion
Rem | Row & Column Information
Set "Row=2"
Set "Column=2"
Rem | Turn Lines To Array Strings
for /f "tokens=* delims=" %%A in ('Type file.csv') do (
set /a "count+=1"
set "Line[!count!]=%%A"
)
Rem | Grab Second Column From Second Row
for /f "tokens=%Column% delims=," %%A in ('Echo !Line[%Row%]!') do (
set "Data=%%A"
)
Echo Second Row, Second Column Data: %Data%
I left a new Rem notes to help you along in the script process.
Just for fun, here's another alternative. You can redirect your csv file into a loop containing two set /P statements -- one to consume the first line, and the second to set a variable to the second line. Then for the line that was captured, use variable substring substitution to strip away *, and ,*.
#echo off & setlocal
(
set /P "="
set /P "val="
) < "output.csv"
set "val=%val:*,=%"
echo %val:,=&rem;%
But really, your attempted solution is almost correct. All that's needed is to break out of the loop after its first iteration.
#echo off & setlocal
set "file=output.csv"
for /f "usebackq skip=1 tokens=2 delims=," %%A in ("%file%") do echo %%A && exit /b
Something like this using more command to skip the first line and simply get the second token each time:
to get only the first value:
#echo off
set "file=output.csv"
for /f "tokens=2 delims=," %%i in ('type order.txt ^| more +1') do echo %%i & goto next
:next
pause
or to get each second column's value:
#echo off
set "file=output.csv"
for /f "tokens=2 delims=," %%i in ('type %file% ^| more +1') do echo %%i
pause

Using if conditions at the end of a FOR loop in Batch

I have a simple for loop in a batch file I'm working on but I can't get the variables to expand correctly. the whole script is below..
setlocal enabledelayedexpansion
set track=0
FOR /f "tokens=2" %%G IN ('find "PhysicalTrackNumber" %1') DO if %track% LSS %%G set track=%%G
echo %track%
echo %1
pause
The for command pulls all the rows with the physical track number and I'm just trying to get the biggest number. IT always stays 0 though when it's comparing. I've tried with !! around my variable as well but then the script seems to do something completely different. I thought it would take the new variable.
What am I missing to compare the outputs to the previous and just get the biggest number?
find "string" filename output consists of
an empty line;
a string of 10 dashes followed by the filename being searched line;
any matching lines of text in the file.
Use skip=2 option (a number of lines to skip at the beginning):
FOR /f "skip=2 tokens=2" %%G IN ('find "PhysicalTrackNumber" "%~1"') DO (
if !track! LSS %%G set "track=%%~G"
)
As an alternative, use findstr instead of find:
FOR /f "tokens=2" %%G IN ('findstr "PhysicalTrackNumber" "%~1"') DO (
if !track! LSS %%G set "track=%%~G"
)

Can't get last 2 characters in token, and for loop returns first token in a vaiable

Ok, here's the set up:
I have a ton of text files with the following format:
filename## time Description of file with spaces
I'm trying to rename the actual file on disk with the description of the file, using a for loop:
FOR /F "tokens=1,2,*" %%a IN (%1) DO call :rename %%a %%b "%%c"
goto :eof
:rename
set origfilename=%1
set last2=%1:~-2%
set time=%2
set "multiword=%~3"
ren %origfilename%.ext "%last2%_%time%_%multiword%.ext"
set origfilename=
set last2=
set time=
set multiword=
Here's what's happening:
last2 is never picking up the last 2 characters of the original file name, and if I echo %3 after the DO instead of the call to :rename, it has the full token with spaces. When I try to use %3 in the loop, it only contains the first token of %3.
I tried using setlocal EnableDelayedExpansion before the for, but it didn't work as I expected.
Am I trying to do too many things at once? Thanks for the help!
Try this. I think this will do what you want.
#echo off
for /f "Tokens=1,2,3*" %%a in ('dir /b filename*') do (
call :rename "%%a %%b %%c %%d" %%a %%b "%%c %%d")
goto :eof
:rename full orig time new
echo %2
set last2=%2
set last2=%last2:~-2%
echo ren "%~1.ext" "%last2%_%3_%~4.ext"
Remove the Echo if everything looks good

Resources