使用cmd按值对文件进行排序

时间:2017-03-22 16:12:29

标签: batch-file cmd

大家好,我在cmd中对SORT命令感到困惑 我试图对包含这些值的speed.txt文本文件进行排序

>  time=1ms  
time=3ms   
 time=267ms  
 time=4ms    
 time=167ms

我使用命令sort /r speed.txt > sorted.txt来输出我期望包含的sorted.txt

>  time=267ms  
time=167ms   
 time=4ms  
 time=3ms    
 time=1ms

但输出是

>  time=4ms  
time=3ms   
 time=267ms  
 time=167ms    
 time=1ms

任何人都可以帮助我获得所需的输出吗?我是cmd命令的新手,我仍处于基本命令

2 个答案:

答案 0 :(得分:1)

@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

使用您的确切上述输入数据的示例输出(假设文件speed.txt):

time=1ms
time=3ms
time=4ms
time=167ms
time=267ms

批处理解析输入,在等号和>处分割字母m处的行(以除去ms)。成功的令牌被计为一个,因此可以选择令牌3。要对数字进行排序(字面意思),它们必须具有相同的长度,我通过向每个数字添加10000并将它们存储在数组中来实现。 / f的第二个用于调用数组,减去先前添加的偏移量10000并以time=#ms

格式输出结果数字

编辑将文件更改为speed.txt

答案 1 :(得分:0)

这是一种可以处理最多八位数甚至重复数字值的方法;它依赖于set命令的排序功能:

@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

以下是使用sort命令和管道|的替代方法:

@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