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

Mun*_*unu 4 windows batch-file

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

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

我尝试过的选项:

  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...行内的所有空格也被修剪(只需要修剪行尾,原始数据文件中不存在)

Mof*_*ofi 5

echo正如Magoo已经写的那样,行尾有一个尾随空格, ECHO不会忽略它。此尾随空格也由ECHO after输出%%c

\n

重定向通常写在命令行末尾,但也可以写在任何地方。也可以将重定向写在开头,如下所示,或者写在中间的某个位置,如本答案中的FOR命令行所示。ECHO命令行的解析与所有其他命令行不同,因为双引号字符串外部的空格字符不会被解释为参数分隔符,因此ECHO命令行中的每个空格字符都很重要,\xc2\xa0is\xc2\xa0 输出为\xc2\xa0 ECHO包括重定向运算符之前的内容,例如.>

\n

这可以很容易地看到

\n
    \n
  • 创建一个批处理文件,echo Test>Test.txt\xc2\xa0其后仅带有尾随空格Test.txt
  • \n
  • 打开命令提示符窗口,并且
  • \n
  • 从命令提示符窗口中运行此批处理文件。
  • \n
\n

输出是echo Test\xc2\xa0\xc2\xa01>Test.txt. So>被 Windows 命令解释器替换为\xc2\xa01>(空格、一、右尖括号),并另外移动到行尾。ECHO命令行上的这种移动会导致最初的尾随空格在文本后面向左移动Test,因此也由ECHO输出。

\n

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

\n
setlocal enabledelayedexpansion\nFOR /F "delims=" %c IN (C:\\Users\\184863\\Desktop\\mydata.txt) DO (echo %c  1>>temp_data.txt )\n(echo [code=119888#!198; ttps://egrul.nalog.ru/]  1>>temp_data.txt )\nendlocal\n
Run Code Online (Sandbox Code Playgroud)\n

现在,后面的尾随空格>>temp_data.txt是在预处理整个FOR命令行之后的,其中命令块仅包含留给 的单个命令\xc2\xa01>>temp_data.txt。当FOR执行ECHO命令行时,尾随空格现在是读取的行之间的附加空格mydata.txt,也由ECHO\xc2\xa01>>temp_data.txt输出。

\n

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

\n

此外,启用了延迟环境变量扩展,这导致在执行ECHO%%c命令之前从Windows 命令解释器处理引用的文件中读取行。行中两个感叹号之间的所有内容都被解释为变量名称,因此如果没有这样的环境变量,则被引用变量的值替换,则什么也不替换。在执行ECHO之前对该行进行额外处理期间,Windows 命令解释器会简单地删除单个(剩余的)感叹号。!VariableName!

\n

解决方案一:

\n
@echo off\nsetlocal EnableExtensions DisableDelayedExpansion\nfor /F "usebackq delims=" %%I in ("%USERPROFILE%\\Desktop\\mydata.txt") do >>temp_data.txt echo(%%I\nendlocal\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

(在命令echo和循环变量引用之间使用而不是空格%%I字符来输出以正确开头的行,而不是命令ECHO/?的使用帮助,因为它会发生在使用时,并且从文本文件读取的行以0 或之后开始更多前导空格/制表符。echo %%Imydata.txt/?

\n

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

\n

由于一行可能以 0 到 9 范围内的数字结尾,因此不好使用:

\n
echo %%c>>temp_data.txt\n
Run Code Online (Sandbox Code Playgroud)\n

最好在ECHOecho %%c命令行的开头指定重定向运算符,然后指定后面不带空格的\xc2\xa0 。请阅读有关使用命令重定向运算符的Microsoft 文档以获取更多信息。

\n

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

\n

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

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

所以在执行前对批处理文件的各个命令行进行预处理后,就可以看出Windows命令解释器最终执行的是哪一行命令行。>>被替换为\xc2\xa01>>(注意开头插入的空格)并且开头的重定向被移动到ECHO命令行的末尾。

\n

另一种解决方案是将命令ECHO括在圆括号中以形成命令块,并仅使用命令ECHO将此命令块的输出重定向到文件,即使用(echo %%c) >>temp_data.txt. 后面的空格数)不再重要。因此(echo %%c)>> temp_data.txt ,在重定向运算符后添加一个空格>>并在行尾添加一个尾随空格会导致文件中的文本temp_data.txt与使用>>temp_data.txt echo %%c.

\n

解决方案2:

\n
@echo off\ncopy /B temp_data.txt+"%USERPROFILE%\\Desktop\\mydata.txt" temp_data.txt >nul\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

这个解决方案肯定比第一个解决方案更好,因为文件包含什么并不重要mydata.txt

\n

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

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