Sorting 如何对包含版本号的文本文件行进行排序,格式为major.minor.build.revision numerical?

Sorting 如何对包含版本号的文本文件行进行排序,格式为major.minor.build.revision numerical?,sorting,batch-file,cmd,Sorting,Batch File,Cmd,我有一个txt文件,其值如下: 3.6.4.2 3.6.5.1 3.6.5.10 3.6.5.11 3.6.5.12 3.6.5.13 3.6.5.2 3.6.7.1 3.6.7.10 3.6.7.11 3.6.7.2 3.6.7.3 我需要编写一个批处理脚本并返回一个排序的输出。问题在于最后一列,数字.10和.11应该在.3之后,依此类推。我需要在底部显示“最新版本”,在本例中为3.6.7.11 在Linux中,我使用了“sort-t”。“-k1n,1-k2n,2-k3n,3-k4n,4”,

我有一个txt文件,其值如下:

3.6.4.2
3.6.5.1
3.6.5.10
3.6.5.11
3.6.5.12
3.6.5.13
3.6.5.2
3.6.7.1
3.6.7.10
3.6.7.11
3.6.7.2
3.6.7.3
我需要编写一个批处理脚本并返回一个排序的输出。问题在于最后一列,数字.10和.11应该在.3之后,依此类推。我需要在底部显示“最新版本”,在本例中为3.6.7.11

在Linux中,我使用了“sort-t”。“-k1n,1-k2n,2-k3n,3-k4n,4”,但我无法使用批处理脚本

此外,由于某些原因,我不允许使用Cygwin或PowerShell

在我的批处理代码中,到目前为止,我只尝试了各种版本的批处理代码,但对我来说没有任何效果:

sort /+n versions.txt
这个问题中使用的输出是简单的

sort versions.txt

看起来命令排序是正确的,直到我没有使用2位数字。

根据您的示例,这将起作用。如果您以某种方式以类似3.6.5.02和3.6.5.2的示例结束,那么此代码将无法工作

@echo off
setlocal EnableDelayedExpansion
for /F "tokens=1-4 delims=. " %%G in (FILE.TXT) do (
   set N=0%%J
   set SORT[%%G%%H%%I!N:~-2!]=%%G.%%H.%%I.%%J
)
for /F "tokens=2 delims==" %%N in ('set SORT[') do echo %%N

pause

根据您的示例,这将起作用。如果您以某种方式以类似3.6.5.02和3.6.5.2的示例结束,那么此代码将无法工作

@echo off
setlocal EnableDelayedExpansion
for /F "tokens=1-4 delims=. " %%G in (FILE.TXT) do (
   set N=0%%J
   set SORT[%%G%%H%%I!N:~-2!]=%%G.%%H.%%I.%%J
)
for /F "tokens=2 delims==" %%N in ('set SORT[') do echo %%N

pause

这是批处理文件中的常见问题。所有排序方法都使用字符串比较,其中“10”位于“2”之前,因此有必要在小于10的数字中插入左零。下面的批处理文件就是这样做的,但它不是生成一个带有固定编号的新文件,而是使用这些编号创建一个将自动排序的数组。之后,数组元素按自然(排序)顺序显示

编辑:为了管理四个部分中的两位数,我修改了代码

@echo off
setlocal EnableDelayedExpansion

for /F "tokens=1-4 delims=." %%a in (input.txt) do (
    rem Patch the four numbers as a two digits ones
    set /A "a=100+%%a, b=100+%%b, c=100+%%c, d=100+%%d"
    rem Store line in the proper array element
    set "line[!a:~1!!b:~1!!c:~1!!d:~1!]=%%a.%%b.%%c.%%d"
)

rem Show array elements
for /F "tokens=2 delims==" %%a in ('set line[') do echo %%a
输出:

3.6.4.2
3.6.5.1
3.6.5.2
3.6.5.10
3.6.5.11
3.6.5.12
3.6.5.13
3.6.7.1
3.6.7.2
3.6.7.3
3.6.7.10
3.6.7.11

这是批处理文件中的常见问题。所有排序方法都使用字符串比较,其中“10”位于“2”之前,因此有必要在小于10的数字中插入左零。下面的批处理文件就是这样做的,但它不是生成一个带有固定编号的新文件,而是使用这些编号创建一个将自动排序的数组。之后,数组元素按自然(排序)顺序显示

编辑:为了管理四个部分中的两位数,我修改了代码

@echo off
setlocal EnableDelayedExpansion

for /F "tokens=1-4 delims=." %%a in (input.txt) do (
    rem Patch the four numbers as a two digits ones
    set /A "a=100+%%a, b=100+%%b, c=100+%%c, d=100+%%d"
    rem Store line in the proper array element
    set "line[!a:~1!!b:~1!!c:~1!!d:~1!]=%%a.%%b.%%c.%%d"
)

rem Show array elements
for /F "tokens=2 delims==" %%a in ('set line[') do echo %%a
输出:

3.6.4.2
3.6.5.1
3.6.5.2
3.6.5.10
3.6.5.11
3.6.5.12
3.6.5.13
3.6.7.1
3.6.7.2
3.6.7.3
3.6.7.10
3.6.7.11

在纯批处理脚本中,可以使用以下代码段:

@echo关闭
setlocal EnableExtensions EnableDelayedExpansion
>“versions.tmp”(
对于/F“usebackq令牌=1,2,3,4 delims=。”(“versions.txt”)中的%%I(
设置“ITEM1=000%%I”&设置“ITEM2=000%%J”&设置“ITEM3=000%%K”&设置“ITEM4=000%%L”
echo!项目1:~-4!。!项目2:~-4!。项目3:~-4!。项目4:~-4!^ |%I.%J.%K.%L
)
)
<“versions.tmp”(
对于/F“tokens=2 delims=|”%%S in('sort')do(
回声%%S
)
)
del/Q“versions.tmp”
端部
退出/B
这将创建一个临时文件,其中包含原始行,前缀为填充版本号和分隔符
|
。填充数字意味着每个组件都用前导零填充到四位数字。以下是一个基于youe示例数据的示例:

然后将该临时文件传递给
排序
,该排序只进行字母排序。因为数字是填充的,所以排序顺序等于真正的字母数字顺序。以下是使用上述示例的排序结果:


最后,如果您只想返回最新版本号,
echo%%S
by
设置“LVER=%%S”
并放置
echo!阿尔弗for/F
循环的
关闭后的


更新: 这里的解决方案不生成任何临时文件,而是使用管道
。由于管道会为左侧和右侧创建新的
cmd
实例,并且由于(控制台)输出是以微小的位构建的,并且执行了多个算术运算,因此速度相当慢:

@echo关闭
setlocal EnableExtensions DisableDelayedExpansion
(
对于/F“usebackq令牌=1,2,3,4 delims=。”(“versions.txt”)中的%%I@(
集合/A“10000+%%I”和回音(^集合/P“=”
集合/A“10000+%%J”和回音(^集合/P“=”
集合/A“10000+%%K”和回音(^集合/P“=”
设置/A“10000+%%L”和回音(
)
) | (
对于/F“标记=1,2,3,4 delims=。”%%S in('sort')do@(
集合/A“%%S-10000”和回音(^集合/P“=”
集合/A“%%T-10000”和回声(^集合/P“=”
集合/A“%%U-10000”和回声(^集合/P“=”
设置/A“%%V-10000”和回音(
)
)
端部
退出/B
管道左侧: 我将
10000
添加到版本号的每个组件中(类似于)为了避免这种情况,因为这在任何一个新的
cmd
实例中都没有启用。为了输出结果值,我利用了一个事实,即
for/F
循环运行在
cmd
上下文中,而不是在
batch
上下文中,
set/A
将结果输出到
STDOUT
set/A
不会以换行符终止其输出,因此我使用
set/P
在每个项目(但最后一个项目除外)后面追加一个
,这反过来不会追加换行符。对于最后一个项目,我使用空白的
echo
追加一个换行符

管道右侧: 排序再次由
sort
命令完成,其输出由
for/F
解析。在此,从每个组件中减去先前增加的值
10000
,以检索原始数字。要将结果输出到控制台,使用与管道另一侧相同的技术

管道数据: 管道传递的数据如下所示(再次依赖于问题的示例):


在纯批处理脚本中,可以使用以下代码段:

@echo关闭
setlocal EnableExtensions EnableDelayedExpansion
>“versions.tmp”(
对于/F“usebackq令牌=1,2,3,4 delims=。”%%I in(“
@echo off
setlocal EnableExtensions EnableDelayedExpansion

set "VersionsFile=versions.txt"

rem Delete all temporary files perhaps existing from a previous
rem run if user of batch file has broken last batch processing.

if exist "%TEMP%\%~n0_?.tmp" del "%TEMP%\%~n0_?.tmp"

rem Insert a leading 0 before each number in version string if the
rem number is smaller than 10. And insert additionally a period at
rem start of each line. The new lines are written to a temporary file.

for /F "useback tokens=1-4 delims=." %%A in ("%VersionsFile%") do (
    if %%A LSS 10 ( set "Line=.0%%A." ) else ( set "Line=.%%A." )
    if %%B LSS 10 ( set "Line=!Line!0%%B." ) else ( set "Line=!Line!%%B." )
    if %%C LSS 10 ( set "Line=!Line!0%%C." ) else ( set "Line=!Line!%%C." )
    if %%D LSS 10 ( set "Line=!Line!0%%D" ) else ( set "Line=!Line!%%D" )
    echo !Line!>>"%TEMP%\%~n0_1.tmp"
)

rem Sort this temporary file with output written to one more temporary file.
rem The output could be also printed to __stdout__ and directly processed.

%SystemRoot%\System32\sort.exe "%TEMP%\%~n0_1.tmp" /O "%TEMP%\%~n0_2.tmp"

rem Delete the versions file before creating new with sorted lines.

del "%VersionsFile%"

rem Read sorted lines, remove all leading zeros after a period and also
rem the period inserted at start of each line making it easier to remove
rem all leading zeros. The lines are written back to the versions file.

for /F "useback delims=" %%L in ("%TEMP%\%~n0_2.tmp") do (
    set "Line=%%L"
    set "Line=!Line:.0=.!"
    set "Line=!Line:~1!"
    echo !Line!>>"%VersionsFile%"
)

rem Finally delete the two temporary files used by this batch file.

del "%TEMP%\%~n0_?.tmp" >nul

endlocal
.03.06.04.02
.03.06.05.01
.03.06.05.10
.03.06.05.11
.03.06.05.12
.03.06.05.13
.03.06.05.02
.03.06.07.01
.03.06.07.10
.03.06.07.11
.03.06.07.02
.03.06.07.03
.03.06.04.02
.03.06.05.01
.03.06.05.02
.03.06.05.10
.03.06.05.11
.03.06.05.12
.03.06.05.13
.03.06.07.01
.03.06.07.02
.03.06.07.03
.03.06.07.10
.03.06.07.11
3.6.4.2
3.6.5.1
3.6.5.2
3.6.5.10
3.6.5.11
3.6.5.12
3.6.5.13
3.6.7.1
3.6.7.2
3.6.7.3
3.6.7.10
3.6.7.11