在文本文件中,我有1000行,每行都有以下数据:
ABCDqwqqwq321890821dsapodsaidadopd-9sa-9asd-9sa00sahjkhjsakdhdsddsad JhKyy120320171212
我需要从每行删除字符(向前90个字符)
并将文件另存为Test_DDMMYYYY.txt
。
以下是我的代码,我无法获得输出。
有什么建议吗?
@echo off &setlocal
(for /f "delims=" %%a in (*.*txt) do (
set "line=%%a"
setlocal enabledelayedexpansion
set "line=!line:~,90!"
echo(!line!
endlocal
))>Test_DDMMYYYY.txt
还使用此代码重命名txt文件:
@echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set "dt=%%a"
set "YY=%dt:~2,2%"
set "YYYY=%dt:~0,4%"
set "MM=%dt:~4,2%"
set "DD=%dt:~6,2%"
set datestamp=%DD%%MM%%YYYY%
set fullstamp=%DD%%MM%%YYYY%
ren "C:\test\Test_.txt" "Test_%fullstamp%.txt"
答案 0 :(得分:0)
将每行不为空且不以分号开头的批处理代码复制到文件名中格式为DDMMYYYY
的本地日期的新文件中,例如在前90个字符后截断每一行可能是例如:
@echo off
if not exist "Test.txt" goto :EOF
setlocal EnableExtensions EnableDelayedExpansion
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalDate=%%I"
set "FileDate=%LocalDate:~6,2%%LocalDate:~4,2%%LocalDate:~0,4%
del "Test_%FileDate%.txt" 2>nul
for /F "usebackq delims=" %%I in ("Test.txt") do set "Line=%%I" & echo !Line:~0,90!>>"Test_%FileDate%.txt"
endlocal
命令
%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE
输出UTF-16 Little Endian编码,例如:
LocalDateTime = 20170513195342.921000 + 120
因此,第一行是空行,第二行包含格式为YYYYMMDD
的本地日期,等号独立于当前用户帐户定义的区域和语言设置。还有2个空行输出。
命令 FOR 在解析UTF-16 LE编码输出时遇到一些问题,这导致将最后一个空行解释为空行,而不是仅包含回车符的行。有关此问题的详细信息,请参阅Batch: How to correct variable overwriting misbehavior when parsing output的答案。
这里使用的命令 FOR 将每一行分成两个子串(标记),因为delims==
使用等号作为分隔符,并且只将第二个字符串分配给循环变量{{ 1}}因为I
。这意味着tokens=2
已分配给环境变量20170513195342.921000+120
。
因为LocalDate
而导致最后一个空行被解释为带有回车符的行的问题,因为只有回车的行不能分成两个令牌,因此 FOR 也忽略了错误解释 WMIC 输出的最后一行空行。
使用带有3个字符串替换的命令 SET ,将本地日期/时间字符串重新格式化为tokens=2
。
提示:使用DDMMYYYY
或更好的可读YYYYMMDD
的文件名在按文件名排序时按日期自动排序。因此,YYYY-MM-DD
或YYYYMMDD
优于YYYY-MM-DD
作为文件名中的日期格式。
如果现有已将输出文件重定向到输出文件上不存在的设备DDMMYYYY
以禁止输出文件,则删除输出文件。
第二个 FOR 解析文件NUL
的行,即使由于选项Test.txt
将文件名括在双引号中也是如此。跳过空行以及以分号开头的行。但是由于选项usebackq
关闭了空格和水平制表符的默认拆分并且仅处理第一个子字符串,所以处理所有其他行而不拆分行。因此,在处理命令行之前,每个非空行不以分号开头都会被赋值给循环变量delims=
。
接下来,该行将分配给环境变量I
。
注1:由于此解决方案旁边需要启用延迟扩展,因此将包含一个或多个感叹号的行无法正确处理,因为将每个感叹号解释为引用的开头或结尾到具有延迟扩展的环境变量。因此,如果文件在每行的前90个字符中也包含感叹号,则需要使用不同的批处理代码。
注2:来自输入文件的有问题的帖子只有68个字符,并且没有发布应该为此行写入输出文件的内容。我希望我理解这项任务是正确的。
使用运算符Line
在一个命令行上指定两个命令,在命令&
之后执行另一个命令,从输入文件输出前90个字符,并从句柄重定向此输出STDOUT 以文件名中的本地日期进行归档,并将此行附加到现有输出文件内容。
在 FOR 循环中将行截断为前90个字符需要延迟扩展或使用不同的代码,例如使用子例程。
一旦输入文件set "Line=%%I"
逐行完全处理,就会恢复上一个命令进程环境并终止批处理文件。
这是一种避免使用延迟扩展的替代解决方案:
Test.txt
此处使用子程序将每行的前90个字符输出到输出文件。
由于
,首先在命令行上指定重定向运算符@echo off
if not exist "Test.txt" goto :EOF
setlocal EnableExtensions DisableDelayedExpansion
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalDate=%%I"
set "FileDate=%LocalDate:~6,2%%LocalDate:~4,2%%LocalDate:~0,4%
del "Test_%FileDate%.txt" 2>nul
for /F "usebackq delims=" %%I in ("Test.txt") do set "Line=%%I" & call :OutputLine
endlocal
goto :EOF
:OutputLine
>>"Test_%FileDate%.txt" echo %Line:~0,90%
goto :EOF
和输出文件名
>>
可能导致立即环境变量扩展,并且在错误的文件输出中以空格和echo %Line:~0,90%>>"Test_%FileDate%.txt"
到1
范围内的数字结尾的行。
如果要输出的行包含对于9
,&
,|
,<
等的Windows命令解释器具有特殊含义的字符,则此解决方案也不起作用。 Windows命令解释器并不是真正用于文本编辑的。文本编辑器专为文本编辑而设计。
重写第一个解决方案来处理当前目录中的每个* .txt文件,但输出文件也写入当前目录。
>
文件内容处理 FOR 循环嵌套在另一个 FOR 循环中,该循环运行命令 DIR 列出所有* .txt文件(而不是因为@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "tokens=2 delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "LocalDate=%%I"
set "FileDate=%LocalDate:~6,2%%LocalDate:~4,2%%LocalDate:~0,4%
del "Test_%FileDate%.txt" 2>nul
for /F "delims=" %%T in ('dir *.txt /A-D /B 2^>nul') do for /F "usebackq delims=" %%I in ("%%T") do set "Line=%%I" & echo !Line:~0,90!>>"Test_%FileDate%.txt"
endlocal
,因为/A-D
为裸格式(文件名和文件扩展名只有路径),因为/B
。
命令 DIR 的文件名列表由外部 FOR 逐行处理,不分割文件名并运行内部 FOR 循环处理文本文件的行。
2^>nul
重定向 DIR 输出的错误消息,如果在当前目录中找不到* .txt文件到设备 NUL 来禁止它。重定向操作符>
必须使用^
进行转义,以便在解析 FOR 命令行时由Windows命令解释程序解释为文字字符,但在执行时作为重定向操作符DIR 命令行在另一个命令进程中由 FOR 启动以执行命令。
2>nul
由 FOR 执行将导致批处理执行退出,因为语法错误,因为 FOR 的重定向不能在命令行中的此位置指定。
另一个变体,它还处理当前目录中的每个* .txt文件。
@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "delims=" %%T in ('dir *.txt /A-D /B 2^>nul') do (
del "%%~nT.tmp" 2>nul
for /F "usebackq delims=" %%I in ("%%T") do set "Line=%%I" & echo !Line:~0,90!>>"%%~nT.tmp"
if exist "%%~nT.tmp" (
%SystemRoot%\System32\fc.exe "%%~nT.tmp" "%%T" /A >nul
if errorlevel 1 ( move /Y "%%~nT.tmp" "%%T" ) else ( del "%%~nT.tmp" )
)
)
endlocal
每个* .txt文件的截断行都写入* .tmp文件,其名称与当前* .txt文件相同,而不是将所有截断的行写入相同的输出文件。
处理* .txt文件后,* .tmp文件如果其内容与* .txt文件的内容不同,则替换* .txt文件。否则,* .tmp文件上的临时文件将被删除,等于* .txt文件,文本文件将保持不变。
所以最后当前目录中的所有* .txt文件都没有超过90个字符的行。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
call /?
del /?
echo /?
endlocal /?
fc /?
for /?
goto /?
if /?
move /?
set /?
setlocal /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?
另请阅读Single line with multiple commands using Windows batch file以及有关Using Command Redirection Operators的Microsoft文章。