[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文本处理] 批处理BAT如何按某字符多少排序?

Toolpath\q\
Toolpath\q\fdf\
Toolpath\q\ewr\
Toolpath\eqwfqf\aff
Toolpath\2

有如上一文档,请问如何按照 \ 字符出现次数排序。排序后成如下:

Toolpath\q\ewr\                               \出现3次
Toolpath\eqwfqf\aff                          \出现2次
Toolpath\q\fdf\                                 \出现2次
Toolpath\q\                                      \出现2次
Toolpath\2                                       \出现1次

凑合着用
  1. @echo off&setlocal enabledelayedexpansion
  2. %1(for /f "tokens=1*" %%a in ('%0 :^|sort /r^|more /t40')do set/am=%%a%%10000&echo,%%b!m!次)&pause&goto :eof
  3. for /f "delims=U" %%a in ('cmd /u /c echo 唉') do set "tab=%%a"
  4. for /f "delims=" %%a in (1.txt) do (
  5.     set "str=%%a"&set "str=!str:\= a!"&set n=99999
  6.     for %%b in (!str!) do set/an+=1
  7.     echo,!n! %%a%tab%\出现
  8. )
复制代码
初学BAT,非专业。代码不适当之处还望前辈们多多指点。在此表示感谢!

TOP

本帖最后由 yhsean 于 2014-4-6 12:08 编辑
  1. set/a n=-1
  2. set mystr=aa\bb\vv\cc\dd\aaa\
  3. setlocal enabledelayedexpansion
  4.    FOR /L %%i in (0,1,1000) do (                                                   
  5.       if "!mystr:~%%i,1!"=="\" set/a n=!n!+1                                            
  6.       if "!mystr:~%%i,1!"==""  echo !n!-%mystr%>>C:\dcam\before_sort && goto _endbefore_sort
  7.     )
  8. endlocal
  9. :_endbefore_sort
复制代码
谢谢,用自己的办法已经解决,没行前加上统计该字符的数字,然后用 sort/R 排序并去掉统计数字输出

TOP

一如既往贴简单暴力的另类解...适用于行数不太多的文件,若要兼容特殊字符需改造,偷懒了:
  1. @echo off&setlocal enabledelayedexpansion >结果.txt
  2. (rd tmp&md tmp) >nul
  3. set /a n=10000
  4. for /f "delims=" %%a in (原文件.txt) do set /a n+=1&echo %%a>tmp\!n:~-4!
  5. (for /f "delims=" %%a in ('dir /o-s /b tmp\*) do type tmp\%%a)>结果.txt
  6. rd tmp >nul
复制代码

TOP

这个用第三方挺爽的,兼容性和效率都没得说:
  1. awk "{print length($0),$0}" a.txt|gnu_sort -knr|sed "s/.....//"
复制代码
length 是 ps 文本对象的自带属性,因为能 sort 所以比 shell 更方便,不过会慢一点:
  1. get-content a.txt|sort-object length|%{$_.length," ",$_}
复制代码

TOP

本帖最后由 CrLf 于 2014-4-7 02:48 编辑

js 的文本也是对象,相比之下会长一点,好处是很容易内嵌 bat 而且兼容性极佳,速度方面应该介于 5 楼的那两个方案之间。
  1. @set @n=0;/*
  2. @echo off
  3. cscript -nologo -e:javascript %0 <a.txt
  4. pause&exit /b
  5. */
  6. var str=WScript.StdIn.ReadAll().split('\n')
  7. str.sort(function(a,b){return a.length - b.length;})
  8. WScript.Echo(str.join('\n'))
复制代码

TOP

vbs 略显操蛋,原本想找找有没简单的办法,最后又绕回 ado...
  1. [原文件] = "a.txt"
  2. [最大行长度] = 65535
  3. Set fso = WScript.CreateObject("Scripting.Filesystemobject")
  4. text = fso.OpenTextFile([原文件],1).ReadAll
  5. Set rec=CreateObject("ADODB.Recordset")
  6. rec.Fields.Append "String",200,[最大行长度]
  7. rec.Fields.Append "Length",200,Len([最大行长度])
  8. rec.Open
  9. For Each str In Split(text,vbCrLf)
  10. rec.AddNew
  11. rec.Fields("String") = str
  12. rec.Fields("Length") = Len(str)
  13. Next
  14. rec.Sort = "Length ASC"
  15. Do Until rec.EOF
  16. Wscript.Echo rec.Fields("String")
  17. rec.MoveNext
  18. Loop
复制代码

TOP

觉得应该按 字符 "\" 的多少排列  不是字符哦

TOP

本帖最后由 apang 于 2014-4-7 11:44 编辑
  1. @set @n=0;/*
  2. @echo off
  3. cscript -nologo -e:javascript %0 <a.txt >b.txt
  4. pause&exit /b
  5. */
  6. var str=WScript.StdIn.ReadAll().split('\n')
  7. str.sort(function(a,b){return b.split('\\').length-a.split('\\').length});
  8. WScript.Echo(str.join('\n'))
复制代码

TOP

发个 PS脚本
  1. $Hash = @{}
  2. get-content .\a.txt | ? {
  3.    $Hash.ADD($_,$_.split("\").Count)
  4. }
  5. $hash.GetEnumerator()| Sort -Descending Value | select -ExpandProperty name
复制代码

TOP

回复 8# terse


    没注意,既然这样...
    不贴另类解简直对不起党中央,简单方便妥妥的,go on:
for /l %%a in ""
  1. @echo off
  2. (rd tmp&md tmp) >结果.txt 2>nul
  3. set "list=\29\28\27\26\25\24\23\22\21\20\19\18\17\16\15\14\13\12\11\10\09\08\07\06\05\04\03\02\01\00"
  4. for /f "delims=" %%a in (原文件.txt) do (
  5. for /f "tokens=31 delims=\" %%b in (".%%a.%list%") do echo %%a>>tmp\%%b.txt
  6. )
  7. type tmp\*.txt>结果.txt 2>nul
  8. pause
复制代码
二号另类解,快速有效:
  1. @echo off&setlocal enabledelayedexpansion
  2. set "原文件=原文件.txt"
  3. set "结果=结果.txt"
  4. set "pattern=[^\\]*"
  5. for %%a in ("%原文件%") do set size=%%~za
  6. (for /l %%a in (1 1 50) do (
  7. for %%b in ("%结果%") do if %%~zb geq %size% exit/b
  8. findstr "^^!pattern!$" "%原文件%"
  9. set "pattern=!pattern!\\[^^\\]*"
  10. ))>"%结果%"
复制代码

TOP

回复 9# apang


    话说感觉用 match 可能会比 split 快,只是猜测,未测试

TOP

本帖最后由 CrLf 于 2014-4-7 20:54 编辑

高冷的 linux 舶来品实现起来如此简单,shell 真是文本专家(如需顺序,把  -nrk 1 换成 -nk 1):
  1. gawk -F"\\" "{print NF,$0}" 原文件.txt | gnu_sort.exe -nrk 1 | sed "s/[0-9] //" >结果.txt
复制代码
再来个纯 gawk 的(如需顺序,把 for(i=asort(ar);i;i--) 换成 for(i=1;i<asort(ar);i++)) :
  1. gawk -F "\\" "{ar[NF+100]=ar[NF+100] RS $0}END{for(i=asort(ar);i;i--) print ar[i];}" 原文件.txt
复制代码

TOP

给几位大佬请安问好。。。。
初学BAT,非专业。代码不适当之处还望前辈们多多指点。在此表示感谢!

TOP

因10楼不能处理重复路径  再发个PS的
话说效率不怎么样
  1. $regex = [RegEx] '\\'
  2. $Filelist = get-content .\a.txt | % {
  3.       New-Object PSObject -Property @{
  4.          Name = $_
  5.          Value = $regex.Matches($_).Count
  6.       }
  7. } | sort -Descending Value
  8. $Filelist | group name|%{$_.Group}|%{$_.Name}|out-file -encoding ASCII "b.txt"
复制代码

TOP

返回列表