我有一个文本文件列出了字母数字代码,如下所示:
17YYUIO
QUICK77
RTY8900
我想要一个修改原始文本文件的批处理文件,所以所有内容都是双倍间隔的,或者只是将结果回显到屏幕,如下所示:
1 7 Y Y U I O P
Q U I C K 7 7 7
R T Y 8 9 0 0 Q
基本上,我试图让Microsoft讲述人从文本文件中读取单个字符,而不是试图将字符作为单词发音的讲述人。
是否可以使用批处理文件在文本文件中的每个字符之间添加空格?
答案 0 :(得分:2)
以下是此任务的完整注释批处理代码:
vector<string> array;
string temp;
array.resize(num);
for(int i = 0; i < num; ++i)
{
cin >> array[i];
}
/* Alternatively:
for(int i = 0; i < num; ++i)
{
cin >> temp;
array.push_back(temp);
}
*/
/* Alternatively:
copy_n(istream_iterator<string>(cin), num, back_inserter(array));
*/
for(int i = 0; i < num; ++i)
{
temp = array[i];
for(int j = 0; j < temp.size(); j += 2)
{
cout << temp[j];
}
}
cout << " ";
for(int i = 0; i < num; ++i)
{
temp = array[i];
for(int j = 1; j < temp.size(); j += 2)
{
cout << temp[j];
}
}
注意:此批处理代码不适用于处理任何文本文件内容,仅适用于仅包含字母数字字符和行终止的ANSI编码文本文件。
要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。
@echo off
setlocal EnableExtensions
rem Define the name of the file to encode by inserting a space
rem character between each alphanumeric character in the file.
set "CodeFile=Test.txt"
rem Define the name of a temporary file with the encoded lines.
set "TempFile=%CodeFile%.tmp"
rem Make sure the temporary file does not already exist.
del "%TempFile%" 2>nul
rem Process each non blank line from file to encode.
for /F "usebackq delims=" %%I in ("%CodeFile%") do call :EncodeLine "%%~I"
rem Overwrite the file to encode with the temporary file
rem with the encoded lines if there was one created at all.
if exist "%TempFile%" move /Y "%TempFile%" "%CodeFile%"
rem Restore previous command environment end exit processing
rem of the batch file without falling through to subroutine.
endlocal
goto :EOF
rem The subroutine EncodeLine inserts a space between each
rem character of the string passed to the subroutine and
rem appends the encoded line to the temporary file.
rem This is done by appending the first character from input
rem line to the current output line after an additionally
rem added space character and removing from input line the
rem just copied first character until the input line does
rem not contain anymore any character.
rem Then output the encoded line without first space character
rem with redirecting the output from handle STDERR to the
rem temporary file with appending the line to temporary file.
rem It is important here to have the redirection operator
rem and the temporary file name on left side before the
rem command ECHO to get correct output if the output line
rem ends with 1 to 9 and avoid adding a trailing space on
rem each output line on writing the line into the file.
rem goto :EOF at end results in exiting the subroutine
rem and returning to FOR command line above.
:EncodeLine
set "InputLine=%~1"
set "OutputLine="
:NextChar
set "OutputLine=%OutputLine% %InputLine:~0,1%"
set "InputLine=%InputLine:~1%"
if not "%InputLine%" == "" goto NextChar
>>"%TempFile%" echo %OutputLine:~1%
goto :EOF
call /?
del /?
echo /?
endlocal /?
for /?
goto /?
if /?
move /?
rem /?
set /?
另请参阅Microsoft文章Using command redirection operators。
答案 1 :(得分:2)
@echo off
setlocal EnableDelayedExpansion
(for /F "delims=" %%a in (input.txt) do (
set "output="
for /F "delims=" %%b in ('cmd /U /C echo %%a^| find /V ""') do (
set "output=!output! %%b"
)
echo !output:~1!
)) > output.txt
rem Replace the input file for the result
move output.txt input.txt /Y
此解决方案充分利用/U
切换cmd.exe
创建 Unicode输出这一事实,即每个输入字符转换为两个输出字节,其中第一个每对的字节是二进制零。这些“0-char”对由find
命令读取,该命令将每个零作为行尾标记。最终结果是%%b
命令中的for
可替换参数以非常简单的方式获取输入行的每个字符。
该程序消除输入文件中的感叹号;如果需要,这一点可以修复。
编辑:修改为回复评论的方法
我修改了原始方法,因此它现在管理几乎所有特殊字符(除引号外):
第二次编辑:我按照dbenham的建议进一步修改了该方法,现在它管理所有字符!
@echo off
setlocal DisableDelayedExpansion
(for /F delims^=^ eol^= %%a in (input.txt) do (
set "str=%%a"
set "output= "
for /F delims^=^ eol^= %%b in ('cmd /V:ON /U /C echo !str!^| find /V ""') do (
setlocal EnableDelayedExpansion
for /F "delims=" %%c in ("!output!") do (
endlocal
set "output=%%c %%b"
)
)
setlocal EnableDelayedExpansion
echo !output:~2!
endlocal
)) > output.txt
rem Replace the input file for the result
move output.txt input.txt /Y
<强> input.txt中:强>
1 7<Y>IO
QU|C"K&7
;T Y!9^0
<强> output.txt的:强>
1 7 < Y > I O
Q U | C " K & 7
; T Y ! 9 ^ 0
如果输出文件中不需要行划分,则可以使用更简单的方法:
set "output="
for /F eol^= %%b in ('cmd /U /C type input.txt ^| find /V ""') do (
set "output=!output! %%b"
)
答案 2 :(得分:0)
这在PowerShell中是微不足道的,但是批处理有点......错误......凌乱:
@echo off
setlocal
set INPUT_FILE=c:\temp\in.txt
for /f "tokens=*" %%L in (%INPUT_FILE%) do call :DO_LINE %%L
endlocal
goto END
:DO_LINE
set LINE_IN=%*
set LINE_OUT=
:DL_LOOP
if "%LINE_IN%" == "" echo %LINE_OUT%&&goto END
if "%LINE_OUT%" == "" (
set LINE_OUT=%LINE_IN:~0,1%
) else (
set LINE_OUT=%LINE_OUT% %LINE_IN:~0,1%
)
set LINE_IN=%LINE_IN:~1%
goto DL_LOOP
goto END
:END
您需要修改设置INPUT_FILE 行。
祝你好运!答案 3 :(得分:0)
这可以做到。我们将使用一个FOR循环,其子程序嵌套在里面。
FOR Loop读取行,LineSpacer
子例程使用substring syntax将它们分隔开来。
@echo OFF
REM - Set your source and destination files.
Set SourceFilePath=C:\Users\Admin\Desktop\SourceFile.txt
Set OutputFilePath=C:\Users\Admin\Desktop\OutputFile.txt
REM Blank out the OutputFile
TYPE nul > %OutputFilePath%
REM For every line in the source text file call linespacer subroutine.
FOR /F "tokens=*" %%A IN (%SourceFilePath%) DO (
SET line=%%A
SETLOCAL EnableDelayedExpansion
SET spacedline=
CALL :LineSpacer
ECHO !spacedline! >> %OutputFilePath%
ENDLOCAL
)
REM - Get the first character of the line, add a space to it
REM - Reset the line variable to one less character, repeat.
:LineSpacer
IF DEFINED line (
SET char=!line:~0,1!
SET "charpluspace=!char! "
SET spacedline=!spacedline!!charpluspace!
SET "line=!line:~1!"
IF "%line%" EQU "!line:~1!" EXIT /b
GOTO linespacer
)
EXIT /b
上面的批处理文件将满足您的需求。为了更好地理解它是如何完成的,请尝试我发布的两个链接中的一些示例。
答案 4 :(得分:0)
我会使用我的JREPL.BAT regular expression command line text processing utility,因为解决方案比任何纯批处理解决方案更简单,更快(忽略实用程序iteslf的复杂性)
写入屏幕
jrepl "(?!^|$)" " " /f file.txt
写入新文件
jrepl "(?!^|$)" " " /f file.txt /o new.txt
覆盖原始
jrepl "(?!^|$)" " " /f file.txt /o -
但是如果你想要一个纯粹的批处理解决方案来替换原始文件,那么我认为这是你能得到的速度,并且仍然支持除null以外的所有字符,保留空白区域,并支持最大长度为~4090的行(插入空格后~8180)。添加cryptic code to compute the length of a string后,逻辑非常简单。但是你可以高效地使用:strlen,即使你不了解它是如何工作的。
@echo off
setlocal disableDelayedExpansion
set "file=%~1"
>"%file%.new" (
for /f "delims=" %%A in ('findstr /n "^" "%file%"') do (
set "in=%%A"
setlocal enableDelayedExpansion
set "in=!in:*:=!"
call :strlen in len
set /a len-=1
set "out="
for /l %%N in (0 1 !len!) do set "out=!out! !in:~%%N,1!"
if defined out (echo(!out:~1!) else echo(
endlocal
)
)
move /y "%file%.new" "%file%" >nul
exit /b
:strlen <stringVar> <resultVar>
(
setlocal EnableDelayedExpansion
set "s=!%~1!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~2=%len%"
exit /b
)