0

I'm trying to create a bat file that I can pass one parameter to that will get written to a text file in a very specific location in the file. The location in the file is unknown from the beginning where it is, but it can be found using hardcoded values.

The structure of the text file:

SECTION1
value1 = 123456
value2 = asdf
value3 = 1111
SECTION2
value1 = 654321
value2 = something
value3 = 875
SECTION3
value1 = 92948
value2 = aaaaaaa
value3 = 6499

The goal is to call the batch file in this manner:

batch.bat somethingelse

... and then have it update exactly and only SECTION2, value2 from "something" to "somethingelse". Like I wrote, I'm perfectly happy to hardcode "SECTION2" and "value2" in the batch file.

This is what I have so far. It's not much. The way I'm approaching it is in three steps, but perhaps this is the wrong way of looking at it:

1: Identify where SECTION2 starts:

for /f "delims=:" %%N in ('findstr /n "SECTION2" "file.txt"') do set section=%%N
echo %section%

2: From the start of %section% find the first occurrence of value2 and store that row number:

Not sure how to accomplish this.

3: At the final row number, overwrite it with "value2 = " + somethingelse, i.e. the first parameter:

This gives me what the row should look like, but I'm not sure how to actually write it.
set output=value2 = %1
echo %output%
InterClaw
  • 3
  • 1

2 Answers2

1

This is much easier done with a script language utilizing full featured regular expressions like PowerShell, being part of windows since version 7 (the -raw parameter requires PSv3+).

To be on topic this PowerShell one liner is wrapped in batch:

powershell -NoP -C "(gc .\file.txt -raw) -replace '(?SM)(?<=SECTION2.*?value2 = ).*?$(?=.*?^[^=]+$)','somethingelse'|Set-Content .\file.txt"

The regular expresson uses (positive) lookarounds to only match value2 between SECTION2/3

Sample output:

SECTION1
value1 = 123456
value2 = asdf
value3 = 1111
SECTION2
value1 = 654321
value2 = somethingelse
value3 = 875
SECTION3
value1 = 92948
value2 = aaaaaaa
value3 = 6499
  • Thanks for your suggestion! I can imagine you can do a lot of powerful things with PS. One problem here though, I didn't specify it, but the name of SECTION3 is unknown and can't be hardcoded in the script, so I don't think this will work. – InterClaw Nov 29 '18 at 23:26
  • Presuming the unknown following section is a line **not** containing an equal sign, I changed the RegEx, should work now. –  Nov 29 '18 at 23:52
  • Sadly there are values that consists of more than one row. However, each section is formatted in this way: [[SECTIONx]] So looking for a row that starts with "[[" should work! – InterClaw Dec 02 '18 at 22:00
0

There are several different ways to solve this problem via a Batch file. This one uses your exact same logic and it is very simple:

@echo off
setlocal

rem 1: Identify where SECTION2 starts:
for /f "delims=:" %%N in ('findstr /n "SECTION2" "file.txt"') do set "section=%%N"

rem 2: From the start of %section% find the first occurrence of value2 and store that row number:
set "firstRow="
for /f "delims=:" %%N in ('findstr /n "value2" "file.txt"') do (
   if %%N gtr %section% if not defined firstRow set "firstRow=%%N"
)

rem 3: At the final row number, overwrite it with "value2 = " + somethingelse, i.e. the first parameter:
(for /F "tokens=1* delims=:" %%N in ('findstr /n "^" "file.txt"') do (
   if %%N neq %firstRow% (
      echo %%O
   ) else (
      echo value2 = %1
   )
)) > newFile.txt

rem Final step: update the new file
move /Y newFile.txt file.txt
Aacini
  • 65,180
  • 12
  • 72
  • 108
  • This is great! However, I have one bug still. I didn't specify it, but the file contains some blank rows and those get replaced by the text `ECHO is off.` as a result here. Is there any way around that? – InterClaw Nov 29 '18 at 23:30
  • replace the line `echo %%O` with `echo(%%O` –  Nov 29 '18 at 23:42
  • That did the trick! Thank you. This makes this solution functional actually, but I'm curious if the regex approach can work as well. :) – InterClaw Dec 02 '18 at 22:02
  • Well, you may select this one as best answer (check the green checkmark). You may also upvote it later, when you have enough rep to do so... – Aacini Dec 02 '18 at 23:29