为什么ECHO命令会在文件中打印一些额外的尾部空间?

我从一个数据文件读取多行并将其附加到另一个文件。 问题是在附加行末尾的输出文件中有一些额外的空间。 根据我的要求修改尾部空格是必须的,因为在原始数据文件中,行尾没有空格。 我尝试了所有可能的事情,但是我仍然无法做到这一点。

@echo off setlocal enabledelayedexpansion FOR /F "delims=" %%c IN (C:\Users\184863\Desktop\mydata.txt) DO ( echo %%c>>temp_data.txt ) endlocal 

我试过的选项:

  1. echo %%c>>temp_data.txt …获得1空间行结束

  2. set lines=%%c
    echo !lines!>>temp_data.txt …得到1行结束

  3. echo !lines:~0,-1!>>temp_data.txt …修剪行的最后一个字符

  4. set lines=!lines: =!
    echo !lines!>>temp_data.txt …行内的所有空格也被修剪(只需要修剪行的末尾,这在原始数据文件中不存在)

你有一个终端空间在echo %%c>>temp_data.txt (等等)应该被删除。 这是终端空间引起的混乱的典型。

echo线末尾有尾随空格,因为Magoo已经写过ECHO没有忽略的部分。 在%%c之后, ECHO也输出这个尾部空格。

重定向通常写在命令行的末尾,但可以在任何地方写入。 也可以在下面或者中间的某个地方写入重定向,就像在这个答案的 FOR命令行中可以看到的一样。 ECHO命令行的解析与所有其他命令行不同,因为双引号字符串之外的空格字符不会被解释为参数分隔符,因此, ECHO命令行中的每个空格字符都很重要,并且由ECHO输出,包括重定向运算符像>

这可以很容易地被看到

  • 创建一个批处理文件,只需在Test.txt后面添加一个尾随空格的echo Test>Test.txt Test.txt
  • 打开命令提示符窗口,并
  • 从命令提示符窗口中运行此批处理文件。

输出是echo Test 1>Test.txt 。 所以>被Windows命令解释器替换为1> (空格,一个,直角括号)并且另外移动到行尾。 ECHO命令行上的这种移动导致最初的尾部空间在文本Test之后左移,因此也由ECHO输出。

在整个命令块的预处理过程中,可以通过在命令提示符窗口中运行没有@echo off原始发布批处理代码来调试批处理文件来查看这个命令行修改。 Windows命令解释器输出与mydata.txt包含单行[code=119888#!198; ttps://egrul.nalog.ru/] [code=119888#!198; ttps://egrul.nalog.ru/]

 setlocal enabledelayedexpansion FOR /F "delims=" %c IN (C:\Users\184863\Desktop\mydata.txt) DO (echo %c 1>>temp_data.txt ) (echo [code=119888#!198; ttps://egrul.nalog.ru/] 1>>temp_data.txt ) endlocal 

>>temp_data.txt后面的尾部空格现在是在整个FOR命令行预处理之后,只包含单个命令的命令块保留为1>>temp_data.txt 。 当FOR执行ECHO命令行时,尾部空间现在是从mydata.txt读取的行与1>>temp_data.txt之间的额外空间,也由ECHO输出。

在预处理/解析命令行之后,应该始终考虑Windows命令解释程序执行的内容,而不是写入批处理文件中的内容。

此外,延迟的环境变量扩展被启用,导致从Windows命令解释器处理的%%c引用的文件的行读取!VariableName! 在执行ECHO命令之前。 行中两个感叹号之间的所有内容都被解释为变量名,因此,如果没有这样的环境变量,则分别用引用变量的值替换。 在ECHO执行之前,在这个额外的线路处理过程中,Windows命令解释程序只会删除一个(剩余的)感叹号。

解决方案1:

 @echo off setlocal EnableExtensions DisableDelayedExpansion for /F "usebackq delims=" %%I in ("%USERPROFILE%\Desktop\mydata.txt") do >>temp_data.txt echo %%I endlocal 

在此批处理代码中,显式禁用延迟的环境变量扩展,以将感叹号始终作为文字字符进行解释。

包含要读取的行的文本文件是使用预定义的Windows环境变量 USERPROFILE指定的,并用双引号括起来,以便在任何Windows计算机上工作。 双引号需要使用选项usebackq来获取带有路径的文件名字符串,解释为文本文件名,从中读取行。

作为一条线可能以1到9范围内的数字结尾,这是不好的使用:

 echo %%c>>temp_data.txt 

最好在ECHO命令行的开头指定重定向操作符,并指定下一个没有尾随空格的echo %%c 。 阅读有关使用命令重定向运算符的Microsoft文章以获取更多信息。

请注意, FOR忽略空行,也忽略所有以分号开始并使用了所选项的行。 ; 是此批处理文件中未明确指定的选项eol (行尾)的默认值。

在运行这个小批处理文件时,在命令提示符窗口@echo off修改为@echo ON ,而不是双击它,可以看到Windows命令解释器真正执行的是什么:

 for /F "usebackq delims=" %I in ("C:\Users\184863\Desktop\mydata.txt") do echo %I 1>>temp_data.txt echo [code=119888#!198; ttps://egrul.nalog.ru/] 1>>temp_data.txt 

因此,在执行之前预处理批处理文件的每个命令行之后,可以看到哪个命令行最终由Windows命令解释器执行。 >>被替换为1>> (注意在开始处插入空格),开始时的重定向被移到了ECHO命令行的末尾。

解决方案2:

 @echo off copy /B temp_data.txt+"%USERPROFILE%\Desktop\mydata.txt" temp_data.txt >nul 

COPY命令可用于将用+运算符指定的多个文件的内容合并成最后指定的单个文件。 此功能用于在现有的temp_data.txt追加用户桌面上mydata.txt的行。 需要选项/B (二进制数据)以避免COPY附加到输出文件temp_data.txt ^ Z,该文件是具有十六进制代码值1A的替代控制字符SUB 。

这个解决方案肯定比第一个更好,因为它不涉及mydata.txt包含的文件。

为了理解使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • copy /?
  • echo /?
  • endlocal /?
  • for /?
  • setlocal /?

这应该是一个简单的修复你。 一:当不需要延迟扩展时,不要使用延迟扩展。二:删除echo命令中的尾随空格。

 @( setlocal echo off SET "_File=C:\Users\184863\Desktop\mydata.txt" SET "_Count=0" SET "_Comment=Your Special Comment " ) FOR /F "tokens=* delims=" %%c IN (%_File%) DO ( CALL :CountEcho %%c ) ( endlocal exit /b 0 ) :CountEcho CALL SET /A "_Count=%_Count% + 1" IF /I %_Count% NEQ 100 ( REM Line Not Equal to 100, Comment it ECHO:%_Comment%%*>>"%~dp0temp_data.txt" ) ELSE ( REM Line 100 - No Comment ECHO:%*>>"%~dp0temp_data.txt" ) GOTO :EOF