标题: [文本处理] [已解决]切割关卡文本的批处理代码要怎样写? [打印本页]
作者: pan528 时间: 2018-7-8 20:37 标题: [已解决]切割关卡文本的批处理代码要怎样写?
我想将关卡集的文本按每个关卡切割,并提取作者姓名、关卡文件名称、关序、关卡名称对每次个关卡重命名。
我写的代码如下,但运行后发现,命名关卡名称不可靠,有部分不能提取,不知道问题出在哪里,请高手指点:- @echo off
-
- COLOR 1F
-
-
- set F1=%~nx1
-
- set /p F1=请输入源目录:
- set F2=Author
-
- echo.
-
-
- echo 1、按关卡切割文本(关卡较大则切割时间较长),请稍候 ...
- echo.
- if not exist %F2% md %F2%
- setlocal enabledelayedexpansion
- for /f "delims=" %%a in ('dir/s /b /on %F1%\*.*')do (
- for /f "delims=" %%i in (%%a)do (
- set m=%%i
- if "!m:~0,5!" == "Level" set x=!m!& echo.>%F2%\%%~na_!x:~5!.txt
- if not "!m:~0,5!" == "Level" echo %%i>>%F2%\%%~na_!x:~5!.txt
- )
- )
-
- :: 将关卡序号改为四位数
- setlocal enabledelayedexpansion
- for /f "tokens=1-3 delims=_" %%i in ('dir /b /o:n %F2%\')do (
- set m=00000%%~nj
- ren "%F2%\%%i_%%j" "%%i_!m:~-5!.txt"
- )
-
- echo 2、加入关卡名称 ...
- setlocal enabledelayedexpansion
- for /f "delims=" %%a in ('dir /b /o %F2%\*.*')do (
- set n=%%a
- for /f "delims=" %%i in (%F2%\%%a)do (
- set m=%%i
- if "!m:~0,5!" == "Title" ren "%F2%\%%a" "!n:~0,-4!_!m:~7!.txt"
- )
- )
-
- :: 剔除空格
- setlocal enabledelayedexpansion
- for /f "delims=" %%a in ('dir/s /b /on %F2%\*.txt')do (
- set "var=%%~na"
- set var=!var:^ ^ =-!
- set var=!var:^ =-!
- set var=!var:--=-!
- ren "%%a" !var!.txt
- )
-
- echo 3、加入作者名称 ...
- setlocal enabledelayedexpansion
- for /f "delims=" %%a in ('dir/s /b /on %F2%\*.*')do (
- for /f "delims=" %%i in (%%a)do (
- set m=%%i
- if "!m:~0,6!" == "Author" set m=!m!&ren "%%a" "!m:~8!_%%~na.txt"
- )
- )
-
- :: 替换字符
- setlocal enabledelayedexpansion
- for /f "delims=" %%a in ('dir/s /b /on %F2%\*.txt')do (
- set "var=%%~na"
- set var=!var:^ ^+^ =,!
- set var=!var:^ ^+=,!
- set var=!var:^+^ =,!
- set var=!var:^+=,!
- set var=!var:^ ^ =-!
- set var=!var:^ =-!
- set var=!var:--=-!
- ren "%%a" !var!.txt
- )
-
-
- echo.
- echo 操作完毕!请检查命名情况,并修正!
- echo.
- echo 按任意键打开 %F2% 目录!
- pause>nul
- start %F2%
- goto:eof
复制代码
会出问题的关卡集:
作者: xxpinqz 时间: 2018-7-9 11:19
把文本的格式转为ansi格式试试。
你自己对比下看看出问题的是否都是复制代码
这样的格式
作者: pan528 时间: 2018-7-9 14:30
回复 2# xxpinqz
谢谢回帖!
我用TextForever转换,或用记事本另存为ansi格式,还是不行。
我猜想:是否一个文本中就包括了两种格式,如果是,有什么工具可彻底转换呢?
还请高手伸出援手。
作者: xxpinqz 时间: 2018-7-9 15:42
文本建议用Notepad+
你这原始文本不能直接另存为ansi格式,得拐个弯:- 1、新建一个文本文档b
- 2、用Notepad打开原始文档a,全选-复制,关闭。
- 3、用Notepad打开新建的文本文档b,粘贴,关闭。
- 4、使用b文档测试看看
复制代码
原理我也不懂哈。。
作者: CrLf 时间: 2018-7-9 22:18
直接告诉我们样本文件的哪一题出的错不好吗?看了半天搞不懂你说的问题在哪里
作者: 狄钦dQ 时间: 2018-7-9 23:28
当批处理执行到“echo 2、加入关卡名称 ...”这一片段,并循环到第48个文件时,字符串会"断节"。
下图截图中提示的“文件名、目录名或卷标语法不正确”,是原来应该被双引号包含的完整文件名,不知道什么原因,后双引号直接把文件名字符串切成两半,从这个后半个引号开始的字符串将以改写模式接在行首(非插入模式),而被切开的后半段文件名就会被覆盖。
以上是我看到的现象,能力有限测试无果,直到7楼大牛点出问题关键,恍然大悟。
步骤1切割得到的90个文件,即使单独使用"2、加入关卡名称 ..."也同样有问题,问题不在第48个文件上,我也测试过在其他位置断节。- @echo off
- setlocal enabledelayedexpansion
- COLOR 1F
- set /a N48=0
- for /f "delims=" %%a in ('dir /b /on Author\*')do (
- set /a N48+=1
- echo %%a !N48!
- if !N48! GEQ 48 pause
- for /f "delims=" %%i in (.\Author\%%a) do (
- echo "%%i"===="我会切开第48个文件名字符串"=====
- )
- )
- echo ---------ok-------- & pause
- goto:eof
复制代码
---------------------------
最后,说个小问题,楼主给的文件,发现一不规范的标题文件,但这不是问题,改改。
作者: WHY 时间: 2018-7-10 11:12
本帖最后由 WHY 于 2018-7-14 17:28 编辑
示例文本很多 Title 行结尾不是以 回车换行(\r\n)结尾,而是以 \r\r\n 结尾
开启变量延迟扩展后,在 set 赋值、截取字符时,多余的回车符 \r 被保留,文件名遇到 \r 导致重命名失败。
把 39 行改成:- if "!m:~0,5!" == "Title" for /f "delims=" %%j in ("!n:~0,-4!_!m:~7!") do ren "%F2%\%%a" "%%j.txt"
复制代码
作者: WHY 时间: 2018-7-10 11:17
本帖最后由 WHY 于 2018-7-14 20:04 编辑
其实脚本有很大的优化空间,举例:- @echo off
- COLOR 1F
-
- set "F1=%~nx1"
- set /p F1=请输入源目录:
- set "F2=Author"
- if not exist "%F2%" md "%F2%"
-
- setlocal enabledelayedexpansion
- for /f "delims=" %%a in ('dir /b /a-d "%F1%\*.txt"') do (
- for /f "delims=" %%i in ('type "%F1%\%%a"') do (
- set "m=%%i"
- if "!m:~0,5!" == "Level" (
- set /a x=10000 + !m:~5!
- echo;>"%F2%\%%~na_!x:~1!.txt"
- ) else (
- echo;%%i>>"%F2%\%%~na_!x:~1!.txt"
- if "!m:~0,5!" == "Title" (
- for /f "delims=" %%j in ("!m:~7!") do set "Title=%%j"
- ) else if "!m:~0,6!" == "Author" (
- set "Author=!m:~8!"
- )
- )
-
- if defined Title if defined Author (
- rem 替换字符
- set "NewName=!Author!_%%~na_!x:~1!_!Title!"
- set "NewName=!NewName: + =,!"
- set "NewName=!NewName: +=,!"
- set "NewName=!NewName:+ =,!"
- set "NewName=!NewName:+=,!"
- set "NewName=!NewName: =-!"
- set "NewName=!NewName: =-!"
- set "NewName=!NewName:--=-!"
-
- rem 重命名
- ren "%F2%\%%~na_!x:~1!.txt" "!NewName!.txt"
- set "Title="
- set "Author="
- )
- )
- )
- pause & exit
复制代码
test.js- var srcDir = '.'; //源目录
- var dstDir = 'Author'; //目标目录
-
- var fso = new ActiveXObject('Scripting.FileSystemObject');
- if(!fso.FolderExists(dstDir)) fso.CreateFolder(dstDir); //创建文件夹
-
- var objFolder = fso.GetFolder(srcDir);
- var e = new Enumerator(objFolder.Files);
-
- for(; !e.atEnd(); e.moveNext()){
- var f = e.item();
- if(!/\.txt$/i.test(f.Name)) continue; //忽略非txt后缀文件
- var baseName = f.Name.replace(/\.txt$/i,'');
-
- var txt = fso.OpenTextFile(f, 1).ReadAll(); //打开、读取文本
- var arr = txt.split(/[\r\n]+Level(?=\d+)/); //分割数组
-
- for(var i=0; i<arr.length; i++) writeToFile(arr[i], baseName);
- }
-
- function writeToFile(str, baseName){
- var num = str.match(/^\d+/); //第一行数字赋值给num
- var author = str.match(/^Author:[^\r\n]+/m);
- var title = str.match(/^Title:[^\r\n]+/m);
-
- if(num && author && title){
- num = (10000 + num * 1 + '').substr(1);
- var newName = author + '_' + baseName + '_' + num + '_' + title;
-
- //删除非法文件名字符,删除 Author: 和 Title:字符,替换字符
- newName = newName.replace(/(Author|Title):\s*|[\\/|<>?*":]/g, '').replace(/\s*\+\s*/g, ',').replace(/\s+/g, '-');
-
- str = str.replace(/^[^\r\n]+/, ''); //删除第一行(数字行)
- fso.CreateTextFile(dstDir + '\\' + newName + '.txt', true).writeLine(str); //写入txt文件
- }
- }
-
- WSH.Echo('Done');
复制代码
作者: 狄钦dQ 时间: 2018-7-10 21:18
示例文本很多 Title 行结尾不是以 回车换行(\r\n)结尾,而是以 \r\r\n 结尾
开启变量延长扩展后,多余的 \ ...
WHY 发表于 2018-7-10 11:12
感谢7楼大佬的点拨,现在我来对@WHY的回答做点补充。首先我们用Winhex工具打开楼主的文本附件,就能看到了文件最真实的样子:
在ASCII标准码表中,换行符(缩写:LF)对应16进制为0A,转义符/n;回车符\r(缩写:CR)对应16进制为0D,转义符/r。从上图观察我们能明显看到:异常的Tile行末多了个0D即回车符\r,从而确定问题的症结。
检查了楼主的文本,这种问题总共出现在7处位置,分别是#18,#86,#123,#154,#150,#169,#188。
那为何用notepad查看文本,并没有发现异常的Title与其他行有什么区别,也都没有换行?
答:对于windows 下标准文本,它只认"\r\n"为换行,单独"\r"或"\n"就直接忽略。但是在其他编辑器就不一定啦,例如用notepad++就能看到异常的Tile换行了。
知道问题关键了,就要说下解决办法:
方法一:8楼@WHY 的示例代码,这里通过取巧的方法避开"字符串断节"——避免在!m:~7!后再继续添加任何字符(方法不治本),这样就能避免字符串在行首改写。
方法二:规范你的数据文本(不干净的数据真的坑),使用notepad++的查找替换(扩展模式),将"\r\r\n"替换成"\r\n"即可,原批处理命令都不用修改了。
作者: codegay 时间: 2018-7-10 23:15
回复 9# 狄钦dQ
补充一下,其实好多编辑器带了类似的功能,是可以显示空白字符的。。nopad++ 点view 然后点 show symbol ,选上show end of line。就可以直接看到\r、\n符了。
作者: codegay 时间: 2018-7-10 23:17
有汉化的notepad++对应估计是查看,显示符号里设置吧。
作者: codegay 时间: 2018-7-10 23:19
notepad++ 在左下角可以切换换行风格,先切成linux再切回windows保存就可以了。
作者: 狄钦dQ 时间: 2018-7-11 07:37
回复 12# codegay
学习了,谢谢
作者: Batcher 时间: 2018-7-11 08:28
Notepad++菜单栏有个按钮可以“显示所有字符”,也能看到CRLF
作者: CrLf 时间: 2018-7-11 09:04
回复 14# Batcher
WTF????
作者: pan528 时间: 2018-7-12 13:00
感谢各位高手相助 !问题解决了。
特别是“狄钦dQ”耐心测试并详细讲解问题发生的原因;“WHY”优化并重编了代码;“codegay、Batcher”介绍了Notepad++使用方法……
再次谢谢!!!
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |