2016-05-13 57 views
1

Hello StackExchange社区!批量排序浮点数

我想解决批处理浮点值的问题。

重点。我有以下形式的日志文件(INPUT.TXT):

889.W_1.153,46 
889.W_1.37,43 
889.W_1.28,81 
889.W_1.34,70 
155.W_2.22,67 
155.W_2.108,06 
155.W_2.22,11 
155 W_2 22,65 

我想在第一和第三列进行排序这一点。我想输出(OUTPUT.TXT)以这种形式:

155.W_2.22,11 
155.W_2.22,65 
155.W_2.22,67 
155.W_2.108,06 
889.W_1.28,81 
889.W_1.34,70 
889.W_1.37,43 
889.W_1.153,46 

我写了一个小剧本,因为我的结果是它的工作原理差不多好了:

155 108,06 W_2 
155 22,11 W_2 
155 22,65 W_2 
155 22,67 W_2 
889 153,46 W_1 
889 28,81 W_1 
889 34,70 W_1 
889 37,43 W_1 

点和列的顺序并不那么重要,实际问题是数字超过2位数。逗号被视为比数字“更高”。以下是脚本:

@echo off 
setlocal enabledelayedexpansion 
for /F "tokens=1-3 delims=." %%a in (INPUT.txt) do set "a[%%a %%c ]=%%b" 
for /F "tokens=2-4 delims=[.]=" %%a in ('set a[') do echo %%a%%c%%b>> OUTPUT.txt 

正确排序并不是我需要的一切。我也有能力(稍后在脚本中)删除一个数字超过2位的整行,在这种情况下,它将与行153,49108,06。任何帮助对我来说都是非常有价值的。

+0

在你的'INPUT.txt'数据样本的最后一行,没有点'。'('155 W_2 22,65');我认为这是一个错字,对吧? – aschipfl

回答

1

纯批处理程序不支持数字排序,需要解决。最好的方法是用零填充数字,然后进行本地字母排序。

要进行实际排序,您可以使用set,正如您在脚本中所做的那样。下面是其特点,所述零填充的批处理文件:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "FILE=%~1" & rem // (1st command line argument: file to process) 
set "RTNF=%~2" & rem // (2nd command line argument: file to store result) 
set /A DIGS=4 & rem // (total number of digits for zero-padding) 
set /A DLIM=2 & rem // (maximum number of digits for 3rd field in file) 

if not defined RTNF set "RTNF=con" 
for /F "eol== delims==" %%V in ('2^> nul set ARRAY[') do set "%%V=" 
setlocal EnableDelayedExpansion 
set "PAD=" & for /L %%D in (1,1,%DIGS%) do set "PAD=!PAD!0" 
endlocal & set "PAD=%PAD%" 
setlocal EnableDelayedExpansion 
for /F usebackq^ delims^=^ eol^= %%L in ("!FILE!") do (
    endlocal 
    for /F "eol=. tokens=1,3,4 delims=., " %%A in ("%%L") do (
     set "FIELD1=%PAD%%%A" 
     set "FIELD3=%%B" 
     set "FIELD4=%%C%PAD%" 
     setlocal EnableDelayedExpansion 
     if "!FIELD3:~%DLIM%!"=="" (
      set "FIELD3=%PAD%!FIELD3!" 
      for /F delims^=^ eol^= %%T in ("!FIELD1:~-%DIGS%!.!FIELD3:~-%DIGS%!,!FIELD4:~,4!") do (
       endlocal 
       set "ARRAY[%%T]=%%L" 
      ) 
     ) else (
      endlocal 
     ) 
    ) 
    setlocal EnableDelayedExpansion 
) 
> "!RTNF!" (
    for /F "tokens=2 delims== eol==" %%I in ('set ARRAY[') do (
     endlocal 
     echo(%%I 
     setlocal EnableDelayedExpansion 
    ) 
) 
endlocal 

endlocal 
exit /B 

对于排序,伪数组变量ARRAY被使用,其索引包含用于排序的适用字段的零填充的数字,的值是输入文件的原始行:

ARRAY[0155.0022,1100]=155.W_2.22,11 
ARRAY[0155.0022,6500]=155 W_2 22,65 
ARRAY[0155.0022,6700]=155.W_2.22,67 
ARRAY[0889.0028,8100]=889.W_1.28,81 
ARRAY[0889.0034,7000]=889.W_1.34,70 
ARRAY[0889.0037,4300]=889.W_1.37,43 

下面是使用一个临时文件和sort COM的另一种方法必须进行分类。这更通用,因为它不会在特殊字符上失败,例如=,这会对基于set命令的方法产生不利影响。这是代码:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "FILE=%~1" & rem // (1st command line argument: file to process) 
set "RTNF=%~2" & rem // (2nd command line argument: file to store result) 
set /A DIGS=4 & rem // (total number of digits for zero-padding) 
set /A DLIM=2 & rem // (maximum number of digits for 3rd field in file) 
set "TMPF=%TEMP%\%~n0_%RANDOM%.tmp" 

if not defined RTNF set "RTNF=con" 
setlocal EnableDelayedExpansion 
set "PAD=" & for /L %%D in (1,1,%DIGS%) do set "PAD=!PAD!0" 
endlocal & set "PAD=%PAD%" 
setlocal EnableDelayedExpansion 
> "!TMPF!" (
    for /F usebackq^ delims^=^ eol^= %%L in ("!FILE!") do (
     endlocal 
     set "LINE=%%L" 
     for /F "eol=. tokens=1,3,4 delims=., " %%A in ("%%L") do (
      set "FIELD1=%PAD%%%A" 
      set "FIELD3=%%B" 
      set "FIELD4=%%C%PAD%" 
      setlocal EnableDelayedExpansion 
      if "!FIELD3:~%DLIM%!"=="" (
       set "FIELD3=%PAD%!FIELD3!" 
       echo(!FIELD1:~-%DIGS%!.!FIELD3:~-%DIGS%!,!FIELD4:~,4!^|!LINE! 
      ) 
      endlocal 
     ) 
     setlocal EnableDelayedExpansion 
    ) 
) 
> "!RTNF!" (
    for /F delims^=^ eol^= %%I in ('sort "!TMPF!"') do (
     endlocal 
     set "LINE=%%I" 
     setlocal EnableDelayedExpansion 
     echo(!LINE:*^|=! 
    ) 
) 
del "!TMPF!" 
endlocal 

endlocal 
exit /B 

用于排序临时文件包含适用字段的零填充的号码的分类,在预定分离器|和输入文件的原始行:

0889.0037,4300|889.W_1.37,43 
0889.0028,8100|889.W_1.28,81 
0889.0034,7000|889.W_1.34,70 
0155.0022,6700|155.W_2.22,67 
0155.0022,1100|155.W_2.22,11 
0155.0022,6500|155 W_2 22,65 
+0

这就是我担心的代码是必要的;-)很好地完成(这也是滥用'set'进行排序的恶作剧:D)。 – Joey

0

你的代码只是需要一个小的调整:

@echo off 
setlocal EnableDelayedExpansion 

for /F "tokens=1-4 delims=.," %%a in (INPUT.txt) do (
    set /A "first=1000+%%a,third=100000+%%c%%d" 
    set "a[!first!!third!]=%%a.%%b.%%c,%%d" 
) 

(for /F "tokens=2 delims==" %%a in ('set a[') do echo %%a) > OUTPUT.txt