在 Windows 中使用批处理脚本对文本文件进行排序
Posted
技术标签:
【中文标题】在 Windows 中使用批处理脚本对文本文件进行排序【英文标题】:Sort a text file with a batch script in windows 【发布时间】:2021-05-21 10:58:58 【问题描述】:我正在做一个学校项目,我需要按用户使用批处理脚本选择的列对文本文件进行排序。
文件如下所示
ID Name Weight Length With Height
052 Chair 1200 100 30 2
077 Bookshelf 5000 120 30 80
096 Cabinet 15000 80 40 85
146 Cupboard 9000 80 60 200
149 Desk 3650 180 100 5
163 Mirror 25800 120 60 70
182 Table 1600 60 60 70
我尝试从这个答案Batch sort by column in file复制解决方案
并修改为6列,代码如下:
setlocal DisableDelayedExpansion
(
for /F "tokens=1-6 delims= " %%A in (%file%) DO (
set "par1=%%A"
set "par2=%%B"
set "par3=%%C"
set "par4=%%D"
set "par5=%%E"
set "par6=%%F"
setlocal EnableDelayedExpansion
echo(!par3! !par1! !par2! !par3! !par4! !par5! !par6!
endlocal
)
) > data.txt.tmp
for /F "usebackq tokens=1,* delims= " %%A in (`sort data.txt.tmp`) DO (
echo(%%B
)
所以我遇到的问题是我希望带有 ID 名称等的第一行保持不变。第二件事是这段代码在按 ID 和名称排序时有效,但是当我得到权重时,它不会正确排序,我得到如下输出:
052 Chair 1200 100 30 2
096 Cabinet 15000 80 40 85
182 Table 1600 60 60 70
163 Mirror 25800 120 60 70
149 Desk 3650 180 100 5
077 Bookshelf 5000 120 30 80
146 Cupboard 9000 80 60 200
ID Name Weight Length With Height
它似乎只是按第一位和第二位数字排序,导致 15000 小于 1600
我怎样才能以最好的方式解决这些问题?
【问题讨论】:
令人惊讶的是,您的数据与昨天刚刚询问的 question 几乎完全相同。 两个问题: 1. 您必须使用skip=1
for for /F
选项将标题排除在排序之外;要将其用于输出,请使用 < %file% (set "HL=" & set /P HL="")
并稍后执行 echo(%HL%
。 2. sort
按字母排序,但您需要的是字母数字排序;要实现这一点,您必须暂时用零填充数字,以使它们包含相同数量的数字,然后您可以按字母顺序等于字母数字顺序。 N. B.: 不需要par#
变量,也不需要延迟扩展;只需使用:echo(%%C %%A %%B %%C %%D %%E %%F
...
@aschipfl 感谢您的实际帮助!
【参考方案1】:
我可能会像以下脚本一样完成您的任务(请参阅所有解释性说明):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=%~1" & rem // (file with data to be sorted)
set "_SCOL=3" & rem // (number of column to sort)
set "_ANUM=#" & rem // (alpha-numeric sorting if not empty)
set "_DESC=" & rem // (descending order if not empty)
set "_TMPF=%TEMP%\%~n0_%RANDOM%.tmp" & rem // (path to temporary file)
rem // Gather TAB character:
for /F "delims=" %%T in ('
forfiles /P "%~dp0." /M "%~nx0" /C "cmd /C echo/0x09"
') do set "_TAB=%%T"
rem // Read first line of file into variable:
< "%_FILE%" (set "HEAD=" & set /P HEAD="") || exit /B
rem // Write to temporary file:
> "%_TMPF%" (
rem // Read all but first line from file line by line:
for /F usebackq^ skip^=1^ delims^=^ eol^= %%L in ("%_FILE%") do (
rem // Store current line string:
set "LINE=%%L"
rem // Extract sort token from current line:
for /F "tokens=%_SCOL% delims=%_TAB% eol=%_TAB%" %%K in ("%%L") do (
rem // Store sort token string:
set "ITEM=%%K"
rem // Toggle delayed expansion to avoid loss of `!`:
setlocal EnableDelayedExpansion
rem // Check if alpha-numeric sorting is desired:
if defined _ANUM (
rem // Check whether sort token only consists of decimal figures:
(for /F "delims=0123456789 eol=0" %%Z in ("!ITEM!") do rem/) || (
rem // Zero-pad sort token to the left up to 12 digits:
set "ITEM=000000000000!ITEM!" & set "ITEM=!ITEM:~-12!"
)
)
rem // Write (padded) sort token plus delimter plus line string:
echo(!ITEM!%_TAB%!LINE!
endlocal
)
)
)
rem // Prepare sort option:
if defined _DESC (set "SOPT=/R") else set "SOPT="
rem // Copy first line, do sorting, strip off sort token, write remainder:
for /F "tokens=1* delims=%_TAB% eol=%_TAB%" %%K in ('
cmd /V /C echo(_!_TAB!!HEAD!^& rem/ ^& ^
sort %SOPT% "%_TMPF%"
') do echo(%%L
rem // Clean up temporary file:
del "%_TMPF%"
endlocal
exit /B
文本文件的路径/名称需要作为命令行参数提供。
【讨论】:
嘿伙计,我收到了关于练习的评论,那就是它需要处理像“White Desk”这样的两部分名称。在 shell 中,我通过在每列之间放置一个制表符,然后在排序命令中使用制表符作为分隔符来解决它。是否有对此代码进行简单修改以批量解决? 好吧,我改编了剧本;之前 tabs 和 spaces 被用作分隔符,现在只使用 tab...以上是关于在 Windows 中使用批处理脚本对文本文件进行排序的主要内容,如果未能解决你的问题,请参考以下文章