-2

I have a variable %data% in a Windows batch file which has variable information in the following format:

URL_A
TEXT
URL_B

So essentially, three strings separated by two newline characters. The length of each string varies on each run. I need to split these three lines into three separate variables. The FOR command seemed promising but there doesn't seem to be a way to specify a newline delimiter for the delim= option.

EDIT (as requested by @Compo):

Here is the batch file's syntax:

play_vid.bat -stream <VID_HEIGHT> <START-TIME> <URL>

Here is the command that generates the %data% variable in my batch file (requires youtube-dl to be installed within the %PATH% environment variable to work):

FOR /F "skip=1 delims=" %%a IN ('youtube-dl --get-title -g -f "bestvideo[height<=%2][fps<=30],worstaudio" --no-playlist "%4"') DO @set data=%%a

Here is a sample command with all the batch variables resolved so that it can be run directly from cmd to test and view the contents of the %data% variable:

FOR /F "skip=1 delims=" %a IN ('youtube-dl --get-title -g -f "bestvideo[height<=1080][fps<=30],worstaudio" --no-playlist "https://www.youtube.com/watch?v=ltynWs_LtIw"') DO @echo %a

For this particular example, %data% will contain:

https://manifest.googlevideo.com/api/manifest/dash/expire/1592941694/ei/HgjyXvilD4ndwQG3nrzoBg/ip/[redacted]
How To Stabilize GoPro Video for Free with FFMPEG
https://manifest.googlevideo.com/api/manifest/dash/expire/1592941694/ei/HgjyXvilD4ndwQG3nrzoBg/ip/[redacted]

that is,

line 1: The URL of the video (DASH) stream.
line 2: The title of the video.
line 3: The URL of the audio (DASH) stream.
Compo
  • 36,585
  • 5
  • 27
  • 39
programmar
  • 670
  • 2
  • 8
  • 18
  • I think that it would be beneficial to potential responses were you to provide the methodology you used to create multiline variables, _before we try to split them up into individual lines_! The two answers you've currently got are both working with a file containing multiple lines, not a multiline variable, and I feel that it's an important enough difference, for me to make this comment. Can you please update your question to provide sufficient information for us to replicate your issue, and assist you with greater focus. – Compo Jun 23 '20 at 13:09
  • @Compo Thanks. Edited it with more info on how the `%data%` variable is made and also included an example. – programmar Jun 23 '20 at 14:08
  • 1
    Your command does not do what you state it does. First of all it outputs three individual lines, the first is exactly the same as the third, and as you've already `skip`ed it you're only getting two lines of output. But as you're using a single `set data=%%a` command, the resultant content of `%data%` will be the content of the last line. The first line content of `%data%` will initially contain the title, i.e. `How To Stabilize GoPro Video for Free with FFMPEG`, which would then be overwritten by the final line, `https://manifest.googlevideo.com/api/manifest/dash/expire/1592947012/ei/…etc.` – Compo Jun 23 '20 at 15:27
  • 2
    Based upon that information, I'd expect code more like **1.** `@For /F "Delims==" %%G In ('Set line[ 2^>NUL') Do Set "%%G="`, _(initially clears the variables)_, **2.** `@For /F "Tokens=1* Delims=[]" %%G In ('youtube-dl --get-title -g -f "bestvideo[height<=1080][fps<=30],worstaudio" --no-playlist "https://www.youtube.com/watch?v=ltynWs_LtIw" 2^>NUL^|%__APPDIR__%find.exe /N /V ""') Do @If %%G Lss 3 Set "line[%%G]=%%H"`, _(to set the first two lines to separate variables)_, and **3.** `@Set line[ & Pause`, _(to quickly view the results)_. – Compo Jun 23 '20 at 15:51
  • @Compo I realize my mistake now thanks to aschipfl and yourself. I'll be editing my question with the final solution. Thanks. – programmar Jun 23 '20 at 15:51
  • programmar, please see my suggested solution in my previous comment, which you may have missed due to writing your own comment. Please also do not update your question to include a solution, that's not appropriate on this site. – Compo Jun 23 '20 at 15:55
  • As you failed to acknowledge my last comment programmar, I have rolled back your latest edit, which went against the advice provided. To explain my commented solution, I was able to determine that your command actually returned the same two lines twice, `title`, `url`, `title`, `url`. I therefore made the code save only the first two lines as individual variables, `%line[1]%` and `%line[2]%`. – Compo Jun 23 '20 at 16:09
  • @Compo My apologies. After my last message I went right to editing my question and so I didn't notice your reply while I was editing. Sorry for the trouble. – programmar Jun 23 '20 at 16:13
  • No worries, please do try the three line batch file in my comment too! – Compo Jun 23 '20 at 16:14
  • @Compo yep, your 3-line solution works like a charm!!! I was just a little troubled as to why the two url outputs from `youtube-dl` are identical since it should not always be the case. I tried with a few other random videos from `YouTube` and they did yield 2 different output urls from the same youtube url input. I'm guessing that it may be a `youtube-dl` bug perhaps, with that particular video I used as a first example. But that would be outside of the scope of the question. I see how I'd have to modify your second line of code to have it store 3 variables instead of 2. Thanks again!!! – programmar Jun 23 '20 at 17:22
  • 1
    You could even, remove `If %%G Lss 3` and use `Do @Set "line[%%G]=%%H"` to have every line individually set as defined variables, in this case `%line[1]%`, `%line[2]%`, `%line[3]%`, and `%line[4]%`. Then you could use your judgement to choose the variables you require for the rest of your task. – Compo Jun 23 '20 at 17:51

2 Answers2

1

I don't know if you mean something like this ?

@echo off
<test.txt (
    set /p Var1= 
    set /p Var2=
    set /p Var3=
)
echo Var1=%Var1%
echo Var2=%Var2%
echo Var3=%Var3%
pause
Hackoo
  • 18,337
  • 3
  • 40
  • 70
  • 2
    Nice, but you should perhaps initially clear the variables, just to make sure empty lines do not result in wrong values (note that `set /P` does not clear the variable on empty input)… – aschipfl Jun 23 '20 at 13:02
1

The for /F command is intended to loop through lines, so line-breaks as delims option would not make much sense. Anyway, you could combine for /F with if defined:

@echo off
rem // Initially clear variables:
set "ONE=" & set "TWO=" & set "THREE="
rem // Read file line by line (note that `eol=;` by default):
for /F "usebackq delims=" %%L in ("data.txt") do (
    if not defined ONE (
        rem // This section is entered in the 1st iteration:
        set "ONE=%%L"
    ) else if not defined TWO (
        rem // This section is entered in the 2nd iteration:
        set "TWO=%%L"
    ) else (
        rem // This section is entered in the 3rd iteration (and further):
        set "THREE=%%L"
    )
)
echo Line 1: %ONE%
echo Line 2: %TWO%
echo Line 3: %THREE%

As an alternative, you could assign a pseudo-array, like this:

@echo off
rem // Initially clear pseudo-array variables:
for /F "delims== eol==" %%V in ('set $LINE[ 2^> nul') do set "%%V="
rem // Read file line by line, precede each one with line number + `:`:
for /F "tokens=1* delims=:" %%K in ('findstr /N "^" "data.txt"') do (
    rem // Assign pseudo-array element with line number as index:
    set "$LINE[%%K]=%%L"
    rem // Conditionally leave loop (optionally):
    if %%K geq 3 goto :NEXT
)
:NEXT
rem // Return result:
set $LINE[

For more information on that topic, refer to this comprehensive answer: Arrays, linked lists and other data structures in cmd.exe (batch) script

aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • Thanks. Your answer showed me the mistakes I was making and eventually led me to the right answer, which I'll be adding to my question. – programmar Jun 23 '20 at 15:54
  • You're welcome, I'm glad that I could help! Please do not add answers to your question, because that's what the answer section is for… – aschipfl Jun 23 '20 at 17:38