找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 21036|回复: 9

[文本处理] [分享]批处理命令sort不读写文件,按字节比较字符串

[复制链接]
发表于 2023-8-31 21:24:53 | 显示全部楼层 |阅读模式

  1. rem csort.bat

  2. @rem 文件后缀名必须是 .bat ,如果是 .cmd 或 .dos,可能造成返回的 errorLevel 和预期不一致。

  3. :main_20230829_224931
  4.         @echo off&setlocal EnableDelayedExpansion
  5.         @rem  10    0x0a           <Line Feed>          换行符    调用方式: !$0a!
  6.         set $0a=^


  7.         @rem  10    0x0a           <Line Feed>          使用 ANSI 编码时,以上必须空两行,必须延迟取值 !$0a!
  8.         echo.
  9.         REM set "arg1=;!a!%0%%~`@#$&,.-_+{}[]\*()=|:"^'<>?/"
  10.         REM set "arg2=;C=Fc"="
  11.         set arg1=&set /p arg1=arg1=
  12.         set arg2=&set /p arg2=arg2=
  13.         cd.
  14.         call :YNC "比较时是否区分大小写?" N && (
  15.                 call :Strcmp arg1 arg2 "/c" && echo arg1 == arg2
  16.                 if !errorlevel! EQU -1 echo arg1 ^< arg2
  17.                 if !errorlevel! EQU  1 echo arg1 ^> arg2
  18.                 cd.&rem 如果不重置的 errorlevel 值,会触发 || 分支。
  19.         ) || (
  20.                 if !errorlevel! EQU 3 (echo "用户中断后续流程。"&cd.&goto :EOF)
  21.                 call :Strcmp arg1 arg2 && echo arg1 == arg2
  22.                 if !errorlevel! EQU -1 echo arg1 ^< arg2
  23.                 if !errorlevel! EQU  1 echo arg1 ^> arg2
  24.                 cd.
  25.         )

  26.         call :Strcmp arg1 "arg2" && echo arg1 == "arg2"
  27.         if !errorlevel! EQU -1 echo arg1 ^< "arg2"
  28.         if !errorlevel! EQU  1 echo arg1 ^> "arg2"

  29.         echo.&pause
  30. @goto :EOF


  31. @rem Usage:
  32. rem                功能: 比较字符串。相等: errorLevel=0; 小于: errorLevel=-1; 大于: errorLevel=1;
  33. rem                      按 C 语言环境比较,即对逐个字节按对应 ASCII 码值比较。默认不区分大小写。
  34. REM                      传递参数用双引号括住,表示传递的是字面字符串,否则传递的是变量名。
  35. rem                      兼容所有特殊字符,如果字符串只是单个双引号,需要赋值给变量,然后把变量名传递给 :strcmp。
  36. rem                      而传递两个双引号,则表示传递空值。
  37. rem                      比较不涉及读写文件,可以在内存中高效运行。
  38. :Strcmp <&s1, &s2, [,/c ...]>
  39.         @echo off||Created by tiandyoin&title Strcmp s1 s2 (ignore case defaultly)
  40.         @setlocal EnableDelayedExpansion
  41.         set guid={D3B20598-09F8-4b22-8B47-BA7778B2C3F4}
  42.         set "so=/L "C"" & if not "%~3"=="" set "so=!so! %~3 "
  43.         if "%~1"=="%1" (set "s1=!%1!") else set "s1=%~1"
  44.         if "%~2"=="%2" (set "s2=!%2!") else set "s2=%~2"
  45.         echo.!so! | findstr /I /C:"/C">nul && (
  46.                 if    "!s1!"=="!s2!" exit /b 0
  47.         ) || (
  48.                 if /i "!s1!"=="!s2!" exit /b 0
  49.         )
  50.         set "!guid!=!s1!!$0a!!guid!=!s2!"
  51.         for /f "delims=" %%a in ('set !guid! ^| sort !so!') do (
  52.                 set guid=
  53.                 setlocal DisableDelayedExpansion
  54.                         set "str=%%a"
  55.                         setlocal EnableDelayedExpansion
  56.                                 if "!str:~39!"=="!s1!" (
  57.                                         @exit /b -1
  58.                                 ) else (
  59.                                         @exit /b 1
  60.                                 )
  61.                         endlocal
  62.                 endlocal
  63.         )
  64. @goto :EOF

  65. :: ---------------------------------------------------------------------------------------------------------------------

  66. @rem Usage:
  67. rem                功能: 判断是否按要求执行命令
  68. :YNC <Prompts ,[Y|N|C]>
  69.         @echo OFF
  70.         set "$=%~2"&if not defined $ set $=Y
  71.         choice /C YNC /T 5 /D %$% /M "%~1 是请按 Y,否请按 N,或者取消请按 C。(5秒后默认为 '%$%')"
  72.         if %errorlevel%==1 goto :YES
  73.         if %errorlevel%==2 goto :NO
  74.         if %errorlevel%==3 goto :CANCEL
  75.           @exit /b 1
  76.         :YES
  77.           @cd.&goto :EOF
  78.         :NO
  79.           @exit /b 2
  80.         :CANCEL
  81.           echo "取消选择。不做任何修改。"
  82.           @exit /b 3
  83. @goto :EOF

复制代码
由于 if 的比较是根据本地语言习惯比较,并不直观。要按字符的ASCII码逐字节比较的,只能想新的办法。
这里利用了 sort /l "c" 的功能,加上管道,很好的比较两个字符串的大小。

评分

参与人数 1技术 +1 收起 理由
buyiyang + 1 感谢分享

查看全部评分

发表于 2023-9-1 00:59:59 | 显示全部楼层
代码完全看不懂,真不愧是强者的世界
发表于 2023-9-1 05:58:32 | 显示全部楼层
字节排序?

  1. @echo off
  2. powershell -noprofile -executionpolicy bypass "[char[]]([System.Text.Encoding]::Default.GetBytes('hello')|sort) -join ''"
  3. pause
复制代码
发表于 2023-9-1 09:28:14 | 显示全部楼层
本帖最后由 buyiyang 于 2023-9-1 09:29 编辑
  1. sort /l "C" /c
复制代码
这里的 /c 是什么意思?

sort好像没有 /c 参数,C区域设置是不分大小写的,为什么加了/c就能区分大小写排序了?

  1. sort /l "C" /
复制代码
我试了一下 / 也能达到同样的效果。

另外,除了了sort参数列表有的之外,我分别拿26个字母做开关参数试了一下,都提示无效命令行开关,除了 /c 和 /u,使用 /u 会使输出成为Unicode。
 楼主| 发表于 2023-9-1 17:57:03 | 显示全部楼层
回复 4# buyiyang


    /c 是区分大小写,应该是有效果的,我再试试
 楼主| 发表于 2023-9-1 18:00:45 | 显示全部楼层
回复 3# Nsqs


    都用 Powershell , 直接跑 ps1 好了。win xp 用不了
 楼主| 发表于 2023-9-1 18:03:33 | 显示全部楼层
回复 3# Nsqs


    只有一个 ’hello‘ ? 怎么排序多个串
 楼主| 发表于 2023-9-1 18:50:58 | 显示全部楼层
回复 4# buyiyang

  1.         set guid={D3B20598-09F8-4b22-8B47-BA7778B2C3F4}
  2.         set s1=AbCdeFGHijklmnooppQs1
  3.         set s2=ABCdeFGHIJKlmnooppQs2
  4.         set s3=AbCdeFGHijklmNOOppQs3
  5.         set s4=abCdefgHijklmnooppQs4
  6.         set s5=AbcDEFGHIJKLMNooppQs5
  7.         set s6=abCdeFghijklMNOOppQs6
  8.         set s7=AbCdeFGHijklmnooppqs7
  9.        
  10.         set "!guid!=!s1!!$0a!!guid!=!s2!!$0a!!guid!=!s3!!$0a!!guid!=!s4!!$0a!!guid!=!s5!!$0a!!guid!=!s6!!$0a!!guid!=!s7!"

  11.         set !guid! | sort /L "C" /C
  12.        
复制代码
结果是有排序的:
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=ABCdeFGHIJKlmnooppQs2
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=AbCdeFGHijklmNOOppQs3
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=AbCdeFGHijklmnooppQs1
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=AbCdeFGHijklmnooppqs7
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=AbcDEFGHIJKLMNooppQs5
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=abCdeFghijklMNOOppQs6
{D3B20598-09F8-4b22-8B47-BA7778B2C3F4}=abCdefgHijklmnooppQs4
发表于 2023-9-1 19:20:09 | 显示全部楼层
回复 5# tiandyoin
sort好像没有 /c 参数,C区域设置也不分大小写,为什么加了/c就能区分大小写排序了?

我是问 /c 开关为什么可以实现区分大小写,因为sort的参数列表和帮助文档都没有这个参数,而且空的开关 / 也能实现相同的功能
 楼主| 发表于 2023-9-8 09:02:55 | 显示全部楼层
回复 9# buyiyang


    我用 Win11 , 你用什么版本

https://ss64.com/nt/sort.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-18 16:44 , Processed in 0.019273 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表