Reputation: 1
Good day guys, i'm kind of confused with the SORT command in cmd im trying to sort a text file which is speed.txt which contains these values
> time=1ms
time=3ms
time=267ms
time=4ms
time=167ms
I used the command sort /r speed.txt > sorted.txt
for it to output sorted.txt which i expect would contain
> time=267ms
time=167ms
time=4ms
time=3ms
time=1ms
but instead the output was
> time=4ms
time=3ms
time=267ms
time=167ms
time=1ms
can anyone help me obtain my desired output ? i'm new to cmd commands i'm still at the basic ones
Upvotes: 0
Views: 340
Reputation: 34909
Here is an approach that can handle numeric values with up to eight digits and even duplicate ones; it relies on the sorting capabilities of the set
command:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~1"
rem /* Store all lines into an array-style variable set `ARRAY[]` with
rem the left-zero-padded time value as the first index, the current
rem line number as the second index to avoid loss of duplicate values
rem and the current line string are the value: */
for /F "tokens=1* delims== eol==" %%K in ('findstr /N "^" "%_FILE%"') do (
set "KEY=%%K" & set "VAL=%%L"
setlocal EnableDelayedExpansion
set /A "NUM=100000000+VAL, LIN=100000000+KEY"
set "KEY=!KEY:*:=!"
for /F "delims=" %%E in ("ARRAY[!NUM:~1!_!LIN:~1!]=!KEY!=!VAL!") do (
endlocal
set "%%E"
)
)
rem // Return values of the array elements sorted by their index:
for /F "tokens=1* delims==" %%K in ('2^> nul set ARRAY[') do (
echo(%%L
)
endlocal
exit /B
Here is an alternative approach using the sort
command and a pipe |
:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~1"
rem /* Precede every line with the sum of `900000000` and the time value,
rem so the resulting number always consists of nine digits, given that
rem the value is less than `100000000`; the prefix is separated from
rem the original text file string by a `|` character; the resulting
rem text is fed into another block of code via a pipe `|`; since pipes
rem instantiate new `cmd` instances for either side, and each side is
rem executed under `cmd` context, the `set /A` command, in contrast to
rem batch file context, returns the (last) result without a trailing
rem line-break, so the text of the next `echo` command is appended;
rem the augmented lines are fed into the `sort` command via a pipe `|`,
rem the prefix is split off using the `|` character (which the original
rem line text must not begin with); `sort` does pure string sorting,
rem but since the number of digits of the prefix is always the same,
rem the alphabetic (string) order equals the numeric order; finally;
rem the prefix is removed from the rest, which is the original text: */
(
rem/ // Read the text file line by line, disregard empty lines:
for /F "usebackq tokens=1* delims== eol==" %%K in ("%_FILE%") do @(
rem/ // Extract the numeric part, add "900000000", return result:
set "VAL=%%L" & set /A "900000000+VAL"
rem/ // Append "|", followed by the original line string:
echo(^^^|%%K=%%L
)
) | (
rem/ /* Feed augmented text into "sort", read output line by line,
rem/ split off "|" and everything in front: */
for /F "tokens=1* delims=|" %%K in ('sort') do @(
rem/ // Return original line string:
echo(%%L
)
)
endlocal
exit /B
Upvotes: 0
Reputation:
@Echo off&SetLocal EnableExtensions EnableDelayedExpansion
for /f "tokens=3 delims=m=^>" %%A in (speed.txt
) do Set /A "time=10000+%%A"&set "T[!time!]=x"
For /f "tokens=2delims=[]" %%A in ('Set T['
) Do Set /A "time=%%A-10000"&Echo time=!time!ms
Sample output with your exact above input data (assuming a file speed.txt):
time=1ms
time=3ms
time=4ms
time=167ms
time=267ms
The batch parses the input splitting the line at the letter m ( to get rid of the ms) at the equal sign and also at the >
. Succesive tokens are counted as one and so it is token 3 to choose. To sort numbers (literally) they have to have the same length, what I accomplish by adding 10000 to each and store them in an array.
The second for /f recalls the array, subtracts the previously added offset 10000 and outputs the resulting number in the format time=#ms
EDIT changed file to speed.txt
Upvotes: 1