如何使用批处理文件在文本文件中的所有字符之间添加空格?

时间:2017-01-01 17:24:55

标签: windows batch-file

我有一个文本文件列出了字母数字代码,如下所示:

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讲述人从文本文件中读取单个字符,而不是试图将字符作为单词发音的讲述人。

是否可以使用批处理文件在文本文件中的每个字符之间添加空格?

5 个答案:

答案 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
)