Page 1 of 1

Linefeed/newline macros

Posted: 27 Feb 2014 00:06
by Liviu
This is posted mostly for (my) reference, since I don't always remember, and never seem to be able to find everything in one place. Below is a set of LF-related macros, with !LF! and %\n% following common usage around here, %/n% being proposed for a linefeed without continuation, and multi-slashed %\\n% %//n% indicating the target depth of expansion.

Code: Select all

@echo off & setlocal disableDelayedExpansion

@rem single linefeed char 0x0A (two blank lines required below)
set LF=^


@rem linefeed macros
set ^"/n=^^^%LF%%LF%^%LF%%LF%"
set ^"//n=^^^^^^%/n%%/n%^^%/n%%/n%"
set ^"///n=^^^^^^^^^^^^%//n%%//n%^^^^%//n%%//n%"
set ^"////n=^^^^^^^^^^^^^^^^^^^^^^^^%///n%%///n%^^^^^^^^%///n%%///n%"
:: set ^"//n=^^^^^^^%LF%%LF%^%LF%%LF%^^^%LF%%LF%^%LF%%LF%"

@rem newline macros (linefeed + line continuation)
set ^"\n=%//n%^^"
set ^"\\n=%///n%^^"
set ^"\\\n=%////n%^^"

setlocal enableDelayedExpansion

@rem check inline expansion
echo(
set ^"NL=^%LF%%LF%"
if '!LF!'=='!NL!' echo '^^!LF^^!'    == '^^^^%%LF%%%%LF%%'

@rem check linefeed macros
echo(
set "ddx=!/n!" & set "edx=!LF!"
call :check && (echo '%%/n%%'    == '^^!LF^^!') || (echo ???)
set "ddx=!//n!" & set "edx=!/n!"
call :check && (echo '%%//n%%'   == '^^!/n^^!') || (echo ???)
set "ddx=!///n!" & set "edx=!//n!"
call :check && (echo '%%///n%%'  == '^^!//n^^!') || (echo ???)
set "ddx=!////n!" & set "edx=!///n!"
call :check && (echo '%%////n%%' == '^^!///n^^!') || (echo ???)

@rem check newline macros
echo(
set "ddx=!\n!" & set "edx=!LF!^"
call :check && (echo '%%\n%%'    == '^^!LF^^!^^^^') || (echo ???)
set "ddx=!\\n!" & set "edx=!/n!^"
call :check && (echo '%%\\n%%'   == '^^!/n^^!^^^^') || (echo ???)
set "ddx=!\\\n!" & set "edx=!//n!^"
call :check && (echo '%%\\\n%%'  == '^^!//n^^!^^^^') || (echo ???)

endlocal & endlocal & goto :eof

:check
set ^"dvar='%ddx%'"
set ^"evar='!edx!'"
if "!dvar!" equ "!evar!" (call;) else (call) & goto :eof
Output:

Code: Select all

'!LF!'    == '^%LF%%LF%'

'%/n%'    == '!LF!'
'%//n%'   == '!/n!'
'%///n%'  == '!//n!'
'%////n%' == '!///n!'

'%\n%'    == '!LF!^'
'%\\n%'   == '!/n!^'
'%\\\n%'  == '!//n!^'

As a use-case for the continuation-less %/n% family would be for/f string loops with embedded newlines, such as...

Code: Select all

:: expected output of each loop is  'x'
::                                  '='
::                                  '"'
::                                  '<'
::                                  '^'

@echo off & setlocal disableDelayedExpansion

@rem single linefeed char 0x0A (two blank lines required below)
set LF=^


@rem linefeed macros
set ^"/n=^^^%LF%%LF%^%LF%%LF%"
set ^"//n=^^^^^^%/n%%/n%^^%/n%%/n%"
set ^"///n=^^^^^^^^^^^^%//n%%//n%^^^^%//n%%//n%"

@rem inline delayed expansion
setlocal enableDelayedExpansion
echo(
for /f "usebackq" %%u in (' x !LF! ^^^= !LF! ^^^" !LF! ^^^< !LF! ^^^^ ') do echo '%%u'

call :test
endlocal
call :test
endlocal & goto :eof

:test
@rem inline percent expansion
echo(
for /f "usebackq" %%u in (' x %/n% ^= %/n% ^" %/n% ^< %/n% ^^ ') do echo '%%u'

@rem 1-deep percent expansion
echo(
set ^"v=x %//n% ^^^= %//n% ^^^" %//n% ^^^< %//n% ^^^^"
for /f "usebackq" %%u in (' %v% ') do echo '%%u'

@rem 2-deep percent expansion
echo(
set ^"v=x %///n% ^^^^^^^= %///n% ^^^^^^^" %///n% ^^^^^^^< %///n% ^^^^^^^^"
set ^"w=%v%"
for /f "usebackq" %%u in (' %w% ') do echo '%%u'

Liviu