Reputation: 505
I have set of files that differs between each others on content and number of rows. However, I want to increment always by 1 the 8th value of the first file line even if the files are different. The values are delimited by semi-colon and could be just a numeric value or a alpha-numeric (i.e. 123 or TBA1).
I've tried to use tokens and loops, but without success. I've just get to actually insert the value and after it the "+1" increment that I was trying to do. My attemps so far is right below
@Echo Off
Set "SrcFile=tf.fic"
Set "OutFile=ntf.text"
If Not Exist "%SrcFile%" Exit /B
( For /F "UseBackQ EOL=, Tokens=1-8* Delims=;" %%A In ("%SrcFile%"
) Do For /F "Tokens=1-2* Delims=" %%I In ("%%H"
) Do Echo=%%A;%%B;%%C;%%D;%%E;%%F;%%G;%%I%%J+1;%%K)>"%OutFile%"
So, taking as an example a file like looks like this:
1;12;A;23;;23;ASD;TTA2;233;HD2;233
1;232;A;b;;A
The output file should have the following content:
1;12;A;23;;23;ASD;TTA3;233;HD2;233
1;232;A;b;;A
Note: some fields may be as empty (i.e. first line 5th field) and should be empty as well on the output file.
Upvotes: 0
Views: 164
Reputation:
Just for comparison, at the cost of readability this PowerShell script could be condensed further:
## Q:\Test\2019\09\12\SO_57905573.ps1
$SrcFile = ".\tf.fic"
$OutFile = ".\ntf.text"
$Content = (Get-Content $SrcFile)
$Firstline = $Content[0] -split ';'
if($Firstline[7] -match '(\d+)$'){
$Firstline[7]=$Firstline[7] -replace $Matches[1],(([int]$Matches[1])+1)
}
$Content[0] = $FirstLine -join ';'
$Content | Set-Content $OutFile
The index in PowerShell is zero based.
Upvotes: 1
Reputation: 2960
I've taken @LotPings comment ("batch isn't suited well for your task as for /f takes successive delimiters as only one") as a challenge and have come up with the following:
@echo off
setlocal enabledelayedexpansion
Set "SrcFile=tf.fic"
Set "OutFile=ntf.text"
If Not Exist "%SrcFile%" Exit /B
If Exist "%OutFile%" del "%OutFile%"
set FIRST=Y
for /f "usebackq tokens=* delims=#" %%x in ( "%SrcFile%" ) do (
set "LINE=%%x"
if defined FIRST (
set "HASH=!LINE:;=;#!"
for /f "usebackq tokens=1-8,* delims=#" %%a in ( '!HASH!' ) do (
set ALPHA=
set NUM=
for /f "tokens=1 delims=0123456789" %%y in ( "%%h" ) do set ALPHA=%%y
for /f "tokens=1 delims=ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%y in ( "%%h" ) do set NUM=%%y
set /a NUM=NUM+1
set "LINE=%%a%%b%%c%%d%%e%%f%%g!ALPHA!!NUM!;%%i"
set "LINE=!LINE:#=!"
)
set FIRST=
)
>>"%OutFile%" echo !LINE!
)
echo ============================ Src
type "%SrcFile%"
echo ============================ Out
type "%OutFile%"
echo ============================
This works both when the eighth field is numeric:
============================ Src
1;12;A;23;;23;ASD;99;233
1;232;A;b;;A
============================ Out
1;12;A;23;;23;ASD;100;233
1;232;A;b;;A
============================
and when it is alphanumeric:
============================ Src
1;12;A;23;;23;ASD;TTA2;233
1;232;A;b;;A
============================ Out
1;12;A;23;;23;ASD;TTA3;233
1;232;A;b;;A
============================
Notes / Explanation
LINE
. Special processing happens only for the first line (when FIRST
is defined).HASH
is created from the first line by replacing all semicolons (;
) with (;#
), turning, for example, aaa;;bbb
into aaa;#;#bbb
.#
is more-or-less arbitrary, so long as it will never appear in a real file.%%a
through %%h
) and "all the rest" (%%i
) as there will always be something between the delimiters, even for empty fields.%%h
) into its (optional) alpha part (ALPHA
) and its numeric part (NUM
). Somewhat perversely, this relies on the fact that adjacent delimiters are "rolled-in to one": the alpha part is delimited by one or more digits; the numeric part is delimited by one or more letters.TTA
) followed by one or more digits (e.g. 2
). If this is not always the case (e.g. if there can be letters after the digit(s)), then adjustments would need to be made.delims=ABC...
clause.SET /A
).#
, the original ;
delimiters are still present, so don't need adding. The only exception is the eighth field, which due to it being further split into two parts will have lost its semicolon.#
characters we added. There won't be any in the first eight fields, but %%i
(the "and all the rest" variable) may contain some.;%%i
).Upvotes: 1
Reputation:
Using some advanced techniques:
:: Q:\Test\2019\09\12\SO_57905573.cmd
@Echo Off & Setlocal EnableDelayedExpansion
Set "SrcFile=tf.fic"
Set "OutFile=ntf.text"
If Not Exist "%SrcFile%" Exit /B
Set /P "FirstLine=" <"%SrcFile%"
Rem create (pseudo)array from FirstLine using self modifying code
Set i=1
Set "FirstLineCol[!i!]=%FirstLine:;="&Set /a i+=1&Set "FirstLineCol[!i!]=%"
rem Set FirstLine
rem strip possible letters from Col[8] and retain number
for /f "delims=ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%N in ("%FirstLineCol[8]%") Do Set /a "Num=%%N,Num1=%%N+1"
set "FirstLineCol[8]=!FirstLineCol[8]:%Num%=%Num1%!"
>"%OutFile%" (
set /p "x=!FirstLineCol[1]!"<NUL
for /l %%L in (2,1,%i%) Do set /p "x=;!FirstLineCol[%%L]!"<NUL
echo(
more +1 "%srcFile%"
)
type "%SrcFile%"
echo:
echo:
type "%OutFile%"
to yield this:
> Q:\Test\2019\09\12\SO_57905573.cmd
1;12;A;23;;23;ASD;TTA2;233;HD2;233
1;232;A;b;;A
1;12;A;23;;23;ASD;TTA3;233;HD2;233
1;232;A;b;;A
Upvotes: 0