简体   繁体   English

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

[英]Why does ECHO command print some extra trailing space into the file?

I am reading multiple lines from a data file and append it to another file.我正在从数据文件中读取多行并将其附加到另一个文件中。 The issue is that some extra space is in output file at end of appended lines.问题是附加行末尾的输出文件中有一些额外的空间。 It is mandatory to trim the trailing space according to my requirement because in original data file there is no space at end of the lines.根据我的要求修剪尾随空格是强制性的,因为在原始数据文件中,行尾没有空格。 I tried all possible things, but I still cannot achieve this one.我尝试了所有可能的事情,但我仍然无法实现这一目标。

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

Options I tried:我试过的选项:

  1. echo %%c>>temp_data.txt ... getting 1 space end of line echo %%c>>temp_data.txt ... 得到 1 个空格的行尾

  2. set lines=%%c
    echo !lines!>>temp_data.txt ... getting 1 space end of line echo !lines!>>temp_data.txt ... 得到 1 个空格的行尾

  3. echo !lines:~0,-1!>>temp_data.txt ... last char of the line trimmed echo !lines:~0,-1!>>temp_data.txt ... 行的最后一个字符被修剪

  4. set lines=!lines: =!
    echo !lines!>>temp_data.txt ... all spaces inside the line are also trimmed (need to trim only end of the line, which is not present in original data file) echo !lines!>>temp_data.txt ... 行内的所有空格也被修剪(只需要修剪行尾,原始数据文件中不存在)

You have a terminal space on the line echo %%c>>temp_data.txt (amongst others) which should be deleted.您在echo %%c>>temp_data.txt (以及其他)行上有一个终端空间,应该删除它。 This is typical of the confusion that terminal spaces causes.这是终端空间引起的典型混淆。

There is a trailing space at end of the echo line as Magoo wrote already which is not ignored by ECHO .正如Magoo已经写的那样,在echo行的末尾有一个尾随空格,它不会被ECHO忽略。 This trailing space is also output by ECHO after %%c .这个尾随空格也由ECHO%%c之后输出。

A redirection is usually written at end of a command line, but it can be written anywhere.重定向通常写在命令行的末尾,但也可以写在任何地方。 It is also possible to write the redirection at beginning as shown below or somewhere in the middle as it can be seen on FOR command line in this answer .也可以在开头编写重定向,如下所示或中间某处,如本答案中的FOR命令行所示 Parsing of an ECHO command line is different to all other command lines as a space character outside a double quoted string is not interpreted as argument separator and for that reason each space character in ECHO command line matters and is output by ECHO including those before redirection operators like > . ECHO命令行的解析与所有其他命令行不同,因为双引号字符串之外的空格字符不会被解释为参数分隔符,因此ECHO命令行中的每个空格字符都很重要并且由ECHO输出,包括重定向运算符之前的那些喜欢>

This can be seen easily by这可以很容易地看出

  • creating a batch file with just echo Test>Test.txt with a trailing space after Test.txt ,创建只是一个批处理文件echo Test>Test.txt与后尾空间Test.txt
  • opening a command prompt window, and打开命令提示符窗口,然后
  • running this batch file from within command prompt window.从命令提示符窗口中运行此批处理文件。

Output is echo Test 1>Test.txt .输出是echo Test 1>Test.txt So > is replaced by Windows command interpreter by 1> (space, one, right angle bracket) and additionally moved to end of line.所以>被 Windows 命令解释器替换为1> (空格,一,右尖括号),并另外移动到行尾。 This movement on ECHO command line results in originally trailing space being moved left after the text Test and is therefore also output by ECHO . ECHO命令行上的这种移动导致最初的尾随空格在文本Test之后向左移动,因此也由ECHO输出。

This command line modification during preprocessing of the entire command block can be seen also by running original posted batch code without @echo off from within a command prompt window to debug the batch file.在整个命令块预处理期间的命令行修改也可以通过在命令提示符窗口中运行原始发布的批处理代码而不使用@echo off来调试批处理文件来查看。 Windows command interpreter outputs with mydata.txt containing the single line [code=119888#!198; ttps://egrul.nalog.ru/] Windows 命令解释器输出mydata.txt包含单行[code=119888#!198; ttps://egrul.nalog.ru/] [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

The trailing space after >>temp_data.txt is now after preprocessing the entire FOR command line with the command block containing only a single command left to 1>>temp_data.txt . >>temp_data.txt之后的尾随空格现在是在预处理整个FOR命令行之后,命令块只包含一个命令,剩下的1>>temp_data.txt When FOR executes the ECHO command line, the trailing space being now an additional space between line read from mydata.txt and 1>>temp_data.txt is also output by ECHO .FOR执行ECHO命令行时,尾随空格现在是从mydata.txt读取的行和1>>temp_data.txt之间的附加空格也由ECHO输出。

It should be always taken into account what is really executed by Windows command interpreter after preprocessing/parsing a command line and not what is written in the batch file.在预处理/解析命令行后,应该始终考虑 Windows 命令解释器真正执行的内容,而不是批处理文件中写入的内容。

Furthermore delayed environment variable expansion is enabled which results in line read from the file referenced with %%c being processed by Windows command interpreter for !VariableName!此外,还启用了延迟环境变量扩展,这会导致从%%c引用的文件中读取行,Windows 命令解释器正在处理!VariableName! before executing the ECHO command.在执行ECHO命令之前。 Everything between two exclamation marks in line is interpreted as variable name and therefore replaced by value of the referenced variable respectively nothing if there is no such environment variable.行中两个感叹号之间的所有内容都被解释为变量名,因此如果没有这样的环境变量,则分别替换为引用变量的值。 A single (remaining) exclamation mark is simply removed by Windows command interpreter during this additional processing of the line before ECHO execution.ECHO执行之前对行进行额外处理期间,Windows 命令解释器会简单地删除一个(剩余的)感叹号。

Solution 1:解决方案1:

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

Delayed environment variable expansion is explicitly disabled in this batch code to interpret exclamation marks always as literal characters.此批处理代码中明确禁用了延迟环境变量扩展,以将感叹号始终解释为文字字符。

There is used ( instead of a space character between the command echo and the loop variable reference %%I to output a line starting with /? correct instead of the usage help of command ECHO as it would happen on using echo %%I and a line read from the text file mydata.txt starts with /? after 0 or more leading spaces/tabs.使用(而不是命令echo和循环变量引用%%I之间的空格字符来输出以/?开头的行正确而不是命令ECHO的使用帮助,因为它会发生在使用echo %%I和 a从文本文件mydata.txt读取的行在 0 个或多个前导空格/制表符后以/?开头。

The text file with the line(s) to read is specified using predefined Windows environment variable USERPROFILE enclosed in double quotes to work on any Windows computer.包含要读取的行的文本文件使用双引号括起来的预定义Windows 环境变量USERPROFILE指定,以便在任何 Windows 计算机上工作。 The double quotes require the option usebackq to get the file name string with path interpreted as text file name from which to read lines.双引号需要选项usebackq来获取文件名字符串,其中路径解释为要从中读取行的文本文件名。

As a line perhaps ends with a number in range 0 to 9 it is not good to use:由于一行可能以 0 到 9 范围内的数字结尾,因此不适合使用:

echo %%c>>temp_data.txt

It is better to specify the redirection operator at beginning of the ECHO command line and specify next the echo %%c with no trailing space.最好在ECHO命令行的开头指定重定向运算符,然后指定没有尾随空格的echo %%c Please read the Microsoft documentation about Using command redirection operator for more information.请阅读有关使用命令重定向运算符的 Microsoft 文档获取更多信息。

Please note that FOR ignores empty lines and also all lines starting with a semicolon with the used options.请注意FOR 会忽略空行以及所有以分号开头的行,并带有所使用的选项。 ; is the default for option eol (end of line) which is not explicitly specified in this batch file.是此批处理文件中未明确指定的选项eol (行尾)的默认值。

On running this small batch file with @echo off modified to @echo ON from within a command prompt window instead of double clicking on it, it can be seen what Windows command interpreter really executes:在运行这个小批处理文件时,@ @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

So it can be seen which command line is finally executed by Windows command interpreter after preprocessing each command line of the batch file before execution.所以在执行前对批处理文件的每个命令行进行预处理后,可以看出Windows命令解释器最终执行的是哪个命令行。 >> was replaced by 1>> (note inserted space at beginning) and the redirection at beginning was moved to end of ECHO command line. >>1>>替换(注意在开头插入空格)并且开头的重定向被移动到ECHO命令行的末尾。

Another solution is enclosing the command ECHO in round brackets to form a command block and redirect the output of this command block with just command ECHO to a file, ie use (echo %%c) >>temp_data.txt .另一种解决方案是在圆括号包围命令ECHO以形成命令块和只用命令ECHO该命令块的输出重定向到一个文件,即使用(echo %%c) >>temp_data.txt The number of spaces after ) do not matter anymore. )之后的空格数不再重要。 Therefore (echo %%c)>> temp_data.txt with a space after redirection operator >> and a trailing space at line end results in same text in file temp_data.txt as on using >>temp_data.txt echo %%c .因此, (echo %%c)>> temp_data.txt在重定向操作符之后带有空格>>和行尾的尾随空格导致文件temp_data.txt文本与使用>>temp_data.txt echo %%c

Solution 2:解决方案2:

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

The COPY command can be use to merge contents of multiple files specified with + operator together into a single file specified last. COPY命令可用于将用+运算符指定的多个文件的内容合并到最后指定的单个文件中。 This feature is used here to append to existing temp_data.txt the lines from mydata.txt on the user´s desktop.此处使用此功能将用户桌面上mydata.txt的行附加到现有temp_data.txt The option /B (binary data) is needed to avoid that COPY appends to output file temp_data.txt ^Z which is the substitute control character SUB with hexadecimal code value 1A.需要选项/B (二进制数据)以避免COPY附加到输出文件temp_data.txt ^Z,它是十六进制代码值 1A 的替代控制字符SUB

This solution is definitely better than the first one as it does not matter what the file mydata.txt contains.这个解决方案肯定比第一个更好,因为文件mydata.txt包含什么无关紧要。

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.要了解使用的命令及其工作原理,请打开命令提示符窗口,在那里执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

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

This should do the needful, including the need to comment line 100.这应该是必要的,包括需要注释第 100 行。

One: Don't use delayed expansion when it isn't necessary.一:没有必要时不要使用延迟扩展。
Two: Remove the trailing space in your echo command.二:删除 echo 命令中的尾随空格。

@(
    SETLOCAL
    ECHO OFF
    SET "_File=C:\Users\184863\Desktop\mydata.txt"
    SET "_Count="
    SET "_Comment=Your Special Comment "
)

FOR /F "tokens=* delims=" %%c IN (%_File%) DO (
    SET /A "Count+=1">NUL
    CALL ECHO.[%COUNT%] | FIND "[100]">NUL && (
        ECHO:%_Comment%%~c
    ) || (
        ECHO.%%c
    )
)>>"%~dp0temp_data.txt"

REM Replace the original file with the commented File
MOVE /Y "%~dp0temp_data.txt" "%_File%"

(
    ENDLOCAL
    EXIT /B 0
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM