sgates3414
sgates3414

Reputation: 3

Looking for batch file to insert new lines into text file

I have a batch file that takes the contents of an image upload directory from an admin portal and generates a text file containing an img src attribute for each image.

At this point each of these text files contains attributes for 20+ images, which I then pull into a div within an aspx page via the c# code behind file.

I am switching to a new layout, so I have to add < / l i > < l i > after every 3 lines.

I am trying to work out how to use a batch file to read the text containing the img src's and insert that code after every 3 lines but I am utterly lost.bat

Upvotes: 0

Views: 4949

Answers (3)

Magoo
Magoo

Reputation: 79983

@ECHO OFF
SETLOCAL
SET count=0
SET injectevery=3
FOR /f "delims=" %%Z IN ('type njacpm.txt^|findstr /n "^"') DO (
SET /a count+=1
SET line=%%Z
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO(!line:*:=!
IF !count!==%injectevery% ECHO.^</li^>^<li^>
ENDLOCAL
SET /a count=count %% %injectevery%
)

Note: adjusted 20130407-1417 per dbenham comment

Now - if NJACPM.TXT contains

===============================
line of text 1

line 3 - 2 was empty
: and this behind colon
but this doesn't
A line of ] many < and >varied %poison ^ characters | like "," and so on
another line
and another

now a real test %path% and !path!
what say you now?
===============================

And the output is:

===============================
line of text 1

line 3 - 2 was empty
</li><li>
: and this behind colon
but this doesn't
A line of ] many < and >varied %poison ^ characters | like "," and so on
</li><li>
another line
and another

</li><li>
now a real test %path% and !path!
what say you now?
===============================

BUT:

serious batchers will understand... and I tried with & too...worked!

  • njacpm.txt ? Now Just A Cotton-Pickin' Minute...

Upvotes: 1

Endoro
Endoro

Reputation: 37569

It could be done easily enough with pure batch using FOR /F to loop through the lines, SET /A to increment a counter, and either delayed expansion or CALL to a subroutine along with an IF statement to add your extra text every 3rd line.

So here you get the pure batch feeling :-)

@echo off
setlocal
set "file=test.txt"
set /a counter=0

(for /f "delims=" %%i in ('^<%file% findstr /n "^"') do call:processline "%%~i")>%file%.new
goto:eof

:processline
set "line=%~1"
set /a check=counter%%3
if %check% equ 0 if %counter% neq 0 echo(^</li^>^<li^>
set /a counter+=1
setlocal enabledelayedexpansion
echo(!line:*:=!
endlocal
exit /b

Edit: added findstr for empty lines.

Upvotes: 1

dbenham
dbenham

Reputation: 130819

It could be done easily enough with pure batch using FOR /F to loop through the lines, SET /A to increment a counter, and either delayed expansion or CALL to a subroutine along with an IF statement to add your extra text every 3rd line.

But I would use a utility that I have already written that performs regex search and replace. It is a hybrid JScript/batch script called REPL.BAT that works on any modern Windows platform. It is very easy to use if you know regular expressions, and it is much faster than any pure batch solution.

It has an M (multiline) option that allows search and replace across line breaks, and an X (eXtended substitution) option that allows escape sequences in the replacement text.

Assuming REPL.BAT is either in your current folder, or else somewhere within your PATH, then the following simple script will insert </li><li> as a new line after every 3rd line in the original.

EDIT: parametized the "inject every" count, and changed \n to \r\n in the replacement string

@echo off
setlocal
set "file=test.txt"
set "count=3"
<"%file%" call repl "((.*\n){%count%})" "$1</li><li>\r\n" mx >"%file%.new"
move /y "%file%.new" "%file%" >nul

Here is the REPL.BAT file that enables the above script to work. It has complete documentation embedded within.

@if (@X)==(@Y) @end /* Harmless hybrid line that begins a JScript comment

::************ Documentation ***********
:::
:::REPL  Search  Replace  [Options  [SourceVar]]
:::REPL  /?
:::
:::  Performs a global search and replace operation on each line of input from
:::  stdin and prints the result to stdout.
:::
:::  Each parameter may be optionally enclosed by double quotes. The double
:::  quotes are not considered part of the argument. The quotes are required
:::  if the parameter contains a batch token delimiter like space, tab, comma,
:::  semicolon. The quotes should also be used if the argument contains a
:::  batch special character like &, |, etc. so that the special character
:::  does not need to be escaped with ^.
:::
:::  If called with a single argument of /? then prints help documentation
:::  to stdout.
:::
:::  Search  - By default this is a case sensitive JScript (ECMA) regular
:::            expression expressed as a string.
:::
:::            JScript syntax documentation is available at
:::            http://msdn.microsoft.com/en-us/library/ae5bf541(v=vs.80).aspx
:::
:::  Replace - By default this is the string to be used as a replacement for
:::            each found search expression. Full support is provided for
:::            substituion patterns available to the JScript replace method.
:::            A $ literal can be escaped as $$. An empty replacement string
:::            must be represented as "".
:::
:::            Replace substitution pattern syntax is documented at
:::            http://msdn.microsoft.com/en-US/library/efy6s3e6(v=vs.80).aspx
:::
:::  Options - An optional string of characters used to alter the behavior
:::            of REPL. The option characters are case insensitive, and may
:::            appear in any order.
:::
:::            I - Makes the search case-insensitive.
:::
:::            L - The Search is treated as a string literal instead of a
:::                regular expression. Also, all $ found in Replace are
:::                treated as $ literals.
:::
:::            E - Search and Replace represent the name of environment
:::                variables that contain the respective values. An undefined
:::                variable is treated as an empty string.
:::
:::            M - Multi-line mode. The entire contents of stdin is read and
:::                processed in one pass instead of line by line. ^ anchors
:::                the beginning of a line and $ anchors the end of a line.
:::
:::            X - Enables extended substitution pattern syntax with support
:::                for the following escape sequences:
:::
:::                \\     -  Backslash
:::                \b     -  Backspace
:::                \f     -  Formfeed
:::                \n     -  Newline
:::                \r     -  Carriage Return
:::                \t     -  Horizontal Tab
:::                \v     -  Vertical Tab
:::                \xnn   -  Ascii (Latin 1) character expressed as 2 hex digits
:::                \unnnn -  Unicode character expressed as 4 hex digits
:::
:::                Escape sequences are supported even when the L option is used.
:::
:::            S - The source is read from an environment variable instead of
:::                from stdin. The name of the source environment variable is
:::                specified in the next argument after the option string.
:::

::************ Batch portion ***********
@echo off
if .%2 equ . (
  if "%~1" equ "/?" (
    findstr "^:::" "%~f0" | cscript //E:JScript //nologo "%~f0" "^:::" ""
    exit /b 0
  ) else (
    call :err "Insufficient arguments"
    exit /b 1
  )
)
echo(%~3|findstr /i "[^SMILEX]" >nul && (
  call :err "Invalid option(s)"
  exit /b 1
)
cscript //E:JScript //nologo "%~f0" %*
exit /b 0

:err
>&2 echo ERROR: %~1. Use REPL /? to get help.
exit /b

************* JScript portion **********/
var env=WScript.CreateObject("WScript.Shell").Environment("Process");
var args=WScript.Arguments;
var search=args.Item(0);
var replace=args.Item(1);
var options="g";
if (args.length>2) {
  options+=args.Item(2).toLowerCase();
}
var multi=(options.indexOf("m")>=0);
var srcVar=(options.indexOf("s")>=0);
if (srcVar) {
  options=options.replace(/s/g,"");
}
if (options.indexOf("e")>=0) {
  options=options.replace(/e/g,"");
  search=env(search);
  replace=env(replace);
}
if (options.indexOf("l")>=0) {
  options=options.replace(/l/g,"");
  search=search.replace(/([.^$*+?()[{\\|])/g,"\\$1");
  replace=replace.replace(/\$/g,"$$$$");
}
if (options.indexOf("x")>=0) {
  options=options.replace(/x/g,"");
  replace=replace.replace(/\\\\/g,"\\B");
  replace=replace.replace(/\\b/g,"\b");
  replace=replace.replace(/\\f/g,"\f");
  replace=replace.replace(/\\n/g,"\n");
  replace=replace.replace(/\\r/g,"\r");
  replace=replace.replace(/\\t/g,"\t");
  replace=replace.replace(/\\v/g,"\v");
  replace=replace.replace(/\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g,
    function($0,$1,$2){
      return String.fromCharCode(parseInt("0x"+$0.substring(2)));
    }
  );
  replace=replace.replace(/\\B/g,"\\");
}
var search=new RegExp(search,options);

if (srcVar) {
  WScript.Stdout.Write(env(args.Item(3)).replace(search,replace));
} else {
  while (!WScript.StdIn.AtEndOfStream) {
    if (multi) {
      WScript.Stdout.Write(WScript.StdIn.ReadAll().replace(search,replace));
    } else {
      WScript.Stdout.WriteLine(WScript.StdIn.ReadLine().replace(search,replace));
    }
  }
}

Upvotes: 2

Related Questions