Reputation: 673
i have a file with the following content:
1005
1010
1011
1012
1013
1014
1009
1015
1006
77
1016
1017
1018
1019
1020
1021
1022
1023
1008
i want to read those lines into an array, sort them and write out chunks with 5 elements into a new file
the output file should looks like this (five elements each line.)
xyz 77,1005,1006,1008,1009
xyz 1010,1011,1012,1013,1014
...
my current batch script looks like this:
@echo off &setlocal disabledelayedexpansion
Sort Knot_unsort.dat>Knot_sort.dat
set /A i=0
for /F "delims=" %%a in (Knot_sort.dat) do (
set /A i+=1
call set array[%%i%%]=%%a
)
call set n=%%i%%
for /L %%i in (1,1,%n%) do (
set /a b = %%i %% 5
if %b% == 0 (
:: does not work
)
call echo %%b%%
)
sorting the content and reading the lines into a array works. but after that i dont know how to concat five elements into a new variable and write them back into a new file. i tried to use modulo but the if statement is not working.
Upvotes: 3
Views: 144
Reputation: 16236
This is relatively straightforward to do. This code get the file content, sorts it, then outputs it in groups of five (5).
powershell -NoProfile -Command ^
"$items = Get-Content -Path '.\Knot_unsort.txt' | Sort-Object { [int]$_ };" ^
"for ($i=0; $i -lt $items.Length; $i+=5) { 'xyz ' + $($items[$i..($i+4)] -join ',') }"
Sample output:
xyz 77 1005 1006 1007 1008
xyz 1009 1010 1012 1013 1014
xyz 1015 1016 1017 1018 1019
xyz 1020 1021 1022 1023
I am not much of a code golfer, but if you need a one-liner:
powershell -nop "$items=gc .\Knot_unsort.txt|sort{[int]$_};for($i=0;$i-lt$items.Length;$i+=5){'xyz '+$($items[$i..($i+4)]-join',')}
Upvotes: 2
Reputation: 67216
Another simpler approach, that don't store the lines in variables...
EDIT: Small bug fixed
@echo off
setlocal EnableDelayedExpansion
set "i=0"
<nul (for /F %%a in ('sort Knot_unsort.dat') do (
set /A "i=(i+1)%%5"
if !i! equ 1 (set /P "=xyz %%a") else set /P "=,%%a"
if !i! equ 0 echo/
))
if %i% neq 0 echo/
Output:
xyz 1005,1006,1007,1008,1009
xyz 1010,1011,1012,1013,1014
xyz 1015,1016,1017,1018,1019
xyz 1020,1021,1022,1023
EDIT: New method to manage numbers with variable number of digits, up to 8
@echo off
setlocal EnableDelayedExpansion
set "i=0"
<NUL (
for /F "tokens=2 delims=/ " %%a in (
'(for /F %%i in (Knot_unsort.dat^) do @(set /A 100000000+%%i ^& echo /%%i^)^) ^| sort'
) do (
set /A "i=(i+1)%%5"
if !i! equ 1 (set /P "=xyz %%a") else set /P "=,%%a"
if !i! equ 0 echo/
)
)
if %i% neq 0 echo/
Upvotes: 2
Reputation: 14290
I normally don't format my code like this but @lit put me up to it.
@echo off & setlocal enabledelayedexpansion
((FOR /F "TOKENS=1* DELIMS=:" %%G IN ('sort Knot_unsort.dat^|findstr /N "^"') DO (set /A "mod=%%G %% 5" &IF !mod! == 0 (echo xyz!line! %%H& set "line=") ELSE (SET "LINE=!LINE! %%H"))) &IF DEFINED LINE echo xyz!line!)>foo.dat
In the real world I would format it like this.
@echo off & setlocal enabledelayedexpansion
((FOR /F "TOKENS=1* DELIMS=:" %%G IN ('sort Knot_unsort.dat^|findstr /N "^"') DO (
set /A "mod=%%G %% 5"
IF !mod! == 0 (echo xyz!line! %%H& set "line=") ELSE (SET "LINE=!LINE! %%H")
)) &IF DEFINED LINE echo xyz!line!)>foo.dat
If you really want to do your array voodoo, you could simplify it to this.
@echo off & setlocal enabledelayedexpansion
for /F "tokens=1* delims=:" %%G in ('sort Knot_unsort.dat^|findstr /N "^"') do (
set "array[%%G]=%%H"&set "n=%%G"
)
((for /L %%I in (1,1,%n%) do (
set /a "mod= %%I %% 5"
IF !mod! == 0 (echo xyz!line! !array[%%I]!&set "line=") ELSE (SET "LINE=!LINE! !array[%%I]!")
))&IF DEFINED LINE echo xyz!line!)>foo.dat
UPDATE: Well they say Imitation is the sincerest form of flattery. I have literally stolen code from @Aacini twice for this updated code. Here and Here
The Windows SORT
command does not sort numerically. So you need to do some Tom Foolery to get it to do that. Here is my updated code.
@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%j in (Knot_unsort.dat) do (
set j=0000000%%j
set name[!j:~-8!]=%%j
)
set "i=0"
<nul (for /F "tokens=2 delims==" %%a in ('set name[') do (
set /A "i=(i+1)%%5"
if !i! equ 1 (set /P "=xyz %%a") else set /P "=,%%a"
if !i! equ 0 echo/
))
if %i% neq 0 echo/
Upvotes: 2
Reputation: 673
i now came up with this code. maybe somebody can use it. if you have a better and easy way i feel free to comment.
@echo off & setlocal enabledelayedexpansion
Sort Knot_unsort.dat>Knot_sort.dat
set /A i=0
for /F "delims=" %%a in (Knot_sort.dat) do (
set /A i+=1
call set array[%%i%%]=%%a
)
call set n=%%i%%
set var=
set newlist=
set /A j=0
for /L %%i in (1,1,%n%) do (
set /a b = %%i %% 5
if !b!==0 (
set /A j+=1
::call echo %%b%%
call set var=%%var%%%%array[%%i]%%,
call set newlist[%%j%%]=%%var%%
call set var=
) else (
call set var=%%var%%%%array[%%i]%%,
)
)
::call echo %j%
call set n=%%j%%
for /L %%i in (1,1,%n%) do (
call echo XYZ - %%newlist[%%i]:~0,-1%%
) >> foo.dat
Upvotes: 1