Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
siberia-man
- Posts: 208
- Joined: 26 Dec 2013 09:28
-
Contact:
#1
Post
by siberia-man » 07 Jun 2015 11:47
heredoc is way to determine multiline string literals in scripts. Unfortunately heredoc is not included to native batch scripts. The following link shows the way to embed heredoc in batch very close to the original definition:
http://stackoverflow.com/a/29329912/3627676I have made some modifications to allow heredoc be declared with the external script "heredoc.bat" or the embedded subroutine ":heredoc". To achieve the goal I used the idea described in the topic
Tricky way to detect calls from another batch script.
Code: Select all
:: http://forum.script-coding.com/viewtopic.php?pid=94390#p94390
@if not defined CMDCALLER @(
(echo on & goto) 2>nul
call set "CMDCALLER=%%~f0"
call "%~f0" %*
set "CMDCALLER="
)
@if /i "%CMDCALLER%" == "%%~f0" set "CMDCALLER="
@echo off
if defined CMDCALLER (
call :heredoc %*
goto :EOF
)
call :heredoc :HEREDOCHELP & goto :EOF
heredoc: attempt to embed the idea of heredoc to batch scripts.
There are few ways for using this solution:
1. call heredoc :LABEL & goto :LABEL
Calling the external script "heredoc.bat" passing the heredoc LABEL.
2. call :heredoc :LABEL & goto :LABEL
Embed the subroutine ":heredoc" into yuor script.
NOTES:
Both LABEL and :LABEL forms are possible. Instead of "goto :LABEL" it is
possible to use "goto" with another label, or "goto :EOF", or "exit /b".
Variables to be evaluated within the heredoc should be called in the
delayed expansion style ^("^!var^!" rather than "%var%", for instance^).
Literal exclamation marks "^!" and carets "^^" must be escaped with a
caret "^".
Additionally, parantheses "(" and ")" should be escaped, as well, if they
are part of the heredoc content within parantheses of the script block.
:HEREDOCHELP
:: http://stackoverflow.com/a/15032476/3627676
:heredoc LABEL
setlocal enabledelayedexpansion
if not defined CMDCALLER set "CMDCALLER=%~f0"
set go=
for /f "delims=" %%A in ( '
findstr /n "^" "%CMDCALLER%"
' ) do (
set "line=%%A"
set "line=!line:*:=!"
if defined go (
if /i "!line!" == "!go!" goto :EOF
echo:!line!
) else (
rem delims are ( ) > & | TAB , ; = SPACE
for /f "tokens=1-3 delims=()>&| ,;= " %%i in ( "!line!" ) do (
if /i "%%i %%j %%k" == "call :heredoc %1" set "go=%%k"
if /i "%%i %%j %%k" == "call heredoc %1" set "go=%%k"
if defined go if not "!go:~0,1!" == ":" set "go=:!go!"
)
)
)
goto :EOF
-
mirrormirror
- Posts: 129
- Joined: 08 Feb 2016 20:25
#2
Post
by mirrormirror » 18 Jul 2016 17:14
Hello Siberia-man, I was attempting to use your heredoc.bat but am not able to get it to work:
Code: Select all
@ECHO OFF
@ECHO BEGIN ---------------------------------------------
CALL heredoc.bat :testlabel1 & goto :testlabel1
DELETE FROM Users;
DROP TABLE IF EXISTS tmpDataInsert;
CREATE TEMP TABLE IF NOT EXISTS [tmpDataInsert] ( [uName] CHAR );
.import SQLImport_UsernNm.txt tmpDataInsert
INSERT INTO Users(UserNm) SELECT * FROM tmpDataInsert;
DROP TABLE IF EXISTS tmpDataInsert;
:testlabel1
@ECHO END ---------------------------------------------
Output:
Code: Select all
T:\>test.cmd
BEGIN ---------------------------------------------
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
,;= " was unexpected at this time.
END ---------------------------------------------
T:\>
Can you advise?
-
siberia-man
- Posts: 208
- Joined: 26 Dec 2013 09:28
-
Contact:
#3
Post
by siberia-man » 19 Jul 2016 00:00
Hi
mirrormirror,
There is error that comes from the line 60 of the heredoc.bat script. Most probably you have entered error while copying from the forum. Please check that you have stored the script correctly. You can take this from the repository
https://github.com/ildar-shaimordanov/c ... eredoc.bat. This is original, working and always actual version of the script.
Last edited by
siberia-man on 07 Aug 2019 12:06, edited 2 times in total.
-
mirrormirror
- Posts: 129
- Joined: 08 Feb 2016 20:25
#4
Post
by mirrormirror » 19 Jul 2016 17:10
Thank you for the reply. I've downloaded the file from the link you sent and the errors are now gone but it doesn't seem to work as expected:
Code: Select all
@ECHO OFF
CALL heredoc.bat :testlabel1 & GOTO :testlabel1
SET DataFile=users.txt
@ECHO BEGIN ---------------------------------------------
:SQLFile_Begin
DELETE FROM Users;
DROP TABLE IF EXISTS tmpDataInsert;
CREATE TEMP TABLE IF NOT EXISTS [tmpDataInsert] ( [uName] CHAR );
.separator "|"
.import %DataFile% tmpDataInsert
INSERT INTO Users(UserNm) SELECT * FROM tmpDataInsert;
DROP TABLE IF EXISTS tmpDataInsert;
:SQLFile_END
:testlabel1
@ECHO END ---------------------------------------------
GOTO:END
Output:
Code: Select all
T:\>test.cmd
END ---------------------------------------------
T:\>
Shouldn't everything between the "CALL heredoc..." and ":testlabel1" be printed out?
-
siberia-man
- Posts: 208
- Joined: 26 Dec 2013 09:28
-
Contact:
#5
Post
by siberia-man » 20 Jul 2016 01:19
I've tested your example. In fact, it doesn't work because you try to call the script by name and extension
.bat. Try the same without extension.
Code: Select all
C:\>type z.bat
@ECHO OFF
CALL heredoc :testlabel1 & GOTO :testlabel1
SET DataFile=users.txt
@ECHO BEGIN ---------------------------------------------
:SQLFile_Begin
DELETE FROM Users;
DROP TABLE IF EXISTS tmpDataInsert;
CREATE TEMP TABLE IF NOT EXISTS [tmpDataInsert] ( [uName] CHAR );
.separator "|"
.import %DataFile% tmpDataInsert
INSERT INTO Users(UserNm) SELECT * FROM tmpDataInsert;
DROP TABLE IF EXISTS tmpDataInsert;
:SQLFile_END
:testlabel1
@ECHO END ---------------------------------------------
GOTO:END
C:\>z
SET DataFile=users.txt
@ECHO BEGIN ---------------------------------------------
:SQLFile_Begin
DELETE FROM Users;
DROP TABLE IF EXISTS tmpDataInsert;
CREATE TEMP TABLE IF NOT EXISTS [tmpDataInsert] ( [uName] CHAR );
.separator "|"
.import %DataFile% tmpDataInsert
INSERT INTO Users(UserNm) SELECT * FROM tmpDataInsert;
DROP TABLE IF EXISTS tmpDataInsert;
:SQLFile_END
END ---------------------------------------------
The system cannot find the batch label specified - END
I'd like to notice that the script outputs everything between the lines
call heredoc :LABEL and
:LABEL and doesn't execute them.
-
mirrormirror
- Posts: 129
- Joined: 08 Feb 2016 20:25
#6
Post
by mirrormirror » 20 Jul 2016 18:10
it doesn't work because you try to call the script by name and extension .bat. Try the same without extension.
Thank you siberia-man, it is working now.