Reputation: 331
I found an answer by Jeb that copies a file to another file including blank lines by adding a number: to the start of every line -
(
set taglinelinks=one two three
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ overview.md"`) do (
set "var=%%a"
if "%var:~0,2%" == "5:" (echo %taglinelinks%)
SETLOCAL EnableDelayedExpansion
set "var=!var:*:=!"
echo(!var!
)
) > new.txt
I added the variable at the top for testing and added the "if" line. It works fine without the "if" line, but I can't see anything wrong with that line. I'm checking to see if the number of the line is 5 and if it is echo the variable to the file then continue on. I should have an else command in my if statement but right now I can't determine what to put there to prevent the rest of the code to skip line 5's original content.
Upvotes: 0
Views: 399
Reputation: 34909
In this answer I stick to our original code and focus on the flaws. Basically I like this approach (with the errors corrected, of course), because this can even properly handle lines that begin with a colon :
, and it does not have any problems with !
appearing in the text file since delayed expansion is toggled.
Anyway, at first I want to show the adapted and working code:
@echo off
setlocal DisableDelayedExpansion
set "taglinelinks=one two three"
> "new.txt" (
for /F "delims=" %%a in ('findstr /N "^" "overview.md"') do (
set "var=%%a"
setlocal EnableDelayedExpansion
if "!var:~,2!" == "5:" (
echo(!taglinelinks!
) else (
echo(!var:*:=!
)
endlocal
)
)
endlocal
And this is what I corrected:
if
clause needs to be in the block with delayed expansion enabled, therefore I moved it one line downwards and I changed %
to !
;else
clause so that it contains the remaining code portion in the for /F
loop bodyendlocal
, so you cannot run into setlocal
nesting limitations, and the set "var=%%a"
command line actually appears in a code section with delayed expansion disabled, which is necessary to not cause trouble with !
appearing in the file;And here are some minor and cosmetic changes:
@echo off
on top in order to avoid command echoes to be written into new.txt
;setlocal
command up to the top to disable delayed expansion at first, so !
could even be safely used in the redirected file name and in the first set
command line (since we might not know whether delayed expansion is disabled or enabled earlier);set
syntax also for the assignment of variable taglinelinks
to make it safe; then I moved this line outside of the redirection block just to become more obvious;usebackq
option is not necessary, so I removed it and used single-quotes ''
(but is just a matter of taste here);findstr
command line appears a bit odd, particularly the escaped caret ^^
, hence I changed quotation so that the search string as well as the file path are quoted, so no such escaping is necessary any more, and the file name may even contain spaces or other special characters;taglinelinks
is not in the block where delayed expansion is enabled; this allows the variable to contain even special characters;set "var=!var:*:=!"
is not really necessary, so I removed it and echoed the truncated string immediately;if
/else
block, to improve readability;> "new.txt"
to the front of the outer parenthesised block to make it more visible (but this is again just a matter of taste here), and I put double-quotes around the file name, so it might even contain spaces or other special characters;endlocal
command that belongs to the initial setlocal
;There is still one thing I do not like in the script, namely the inflexible way to identify the number of the current line, because it currently only works for numbers less than 10
without adapting the code a bit.
Here is a way to flexibly specify the number of the line to replace:
@echo off
setlocal DisableDelayedExpansion
set "taglinelinks=one two three"
set "linenumber=5"
> "new.txt" (
for /F "delims=" %%a in ('findstr /N "^" "overview.md"') do (
set "var=%%a"
setlocal EnableDelayedExpansion
set /A "num=var"
if !num! equ !linenumber! (
echo(!taglinelinks!
) else (
echo(!var:*:=!
)
endlocal
)
)
endlocal
This is what I did:
linenumber
with the line number 5
; regard that linenumber
must not hold leading zeros for the number not to be interpreted as octal integer later (by if
);set /A "num=var"
, which makes use of implicit variable expansion of set /A
, meaning that the line string is scanned from left to right up to the first non-numeric character1, then this string is converted to an integer and finally assigned to num
; this implies that the file contains less than 231 lines;if
clause is changed to if !num! equ !linenumber!
, which performs a numeric comparison due to equ
since both expressions are integers; so this no longer depends on the number of digits of the line number; here I could also have used %linenumber%
since the variable is not changed in the code block, but I decided to use !linenumber!
to cover the case of wrong initialisation of that variable (particularly when it is blank or contains special characters due to typos);1) Actually leading SPACEs and TABs are ignored. Next a single +
or -
sign may occur. Then everything up to the next non-numeric figure is used to convert the string into a signed 32-bit integer. If the result cannot be represented as such it becomes coerced.
Upvotes: 2
Reputation: 38623
You could try it like this:
@Echo Off
Set "taglinelinks=one two three"
( For /F "Tokens=1*Delims=:" %%A in ('Findstr /N "^" "overview.md"')Do (
If %%A NEq 5 (Echo=%%B)Else Echo %taglinelinks%
)
)>"new.txt"
Upvotes: 1