1

我正在尝试从批处理文件中调用命令,该批处理文件正在从文件中读取行。
这工作正常,除非该行包含重定向字符>

有没有办法告诉call转义这个字符,或者在 for 循环的内容中替换它?

我看过setlocal enabledelayedexpansionand (当调用更新为使用!它仍然不起作用)。

set /p status=<%tmp_file%

for /f "delims=*" %%a in (%tmp_file%) do (
  echo "%%a"
  call check.bat "%%a"
  echo.

  if not "%errorlevel%" == "0" do exit /b 1
)

这会产生以下输出(当check.batecho's时%1

"a"
"a"

"b -> b"
"b -"

我尝试在其中替换>%%a但我不完全确定如何实现,每次尝试时,它都会产生一个空字符串,即

set line=%a:^>=¬%

编辑 1更多说明(如果设置为变量,然后使用该变量,
似乎只有这种情况)?:%1

check.bat

 set rawinput=%1
 set input=%~1

 echo %1
 echo "%rawinput%"
 echo "%input%"
 echo.

这会产生以下输出,尽管我不太确定为什么设置%1变量会导致它破坏值?

 "a"
 "a"
 ""a""
 "a"

 "b -> b"
 "b -> b"
 "b -"

有趣b -> b的是只输出2次,echo "%rawinput%"根本没有显示。两者echo "%input%"echo "%rawinput%"都在写入一个名为b.

这意味着check.batforb -> b必须解释为:

 echo "b -> b"
 echo ""b -> b""
 echo "b -> b"        REM - this is what 'should' be happening, however does appear to be the case, as it writes '' to a file named b
 echo.

如果有人可以阐明为什么echo "b -> b"批处理文件中的行为似乎没有表现,将不胜感激。

4

2 回答 2

3

不要尝试使用call by value,这对于批处理几乎是不可能的。
只需使用值设置一个新变量,然后使用变量名称。

for /f "delims=" %%a in (%tmp_file%) do (
  set "line=%%a"
  call :check
)
exit /b

:check
setlocal EnableDelayedExpansion
echo(!line!
endlocal
exit /b

编辑:你的问题

您尝试"b -> b"使用
call check.bat "%%a"this 调用内容的函数将扩展为
call check.bat ""b -> b"",这就是问题所在!
由于>重定向字符现在在引号之外,它会将 check.bat 的输出重定向到文件b
使用调用时可​​以转义特殊字符(引号之外),但这有点高级并且有很多问题。

所以,我再次推荐,不要直接在通话中使用内容。
您可以使用参考,例如

for /f "delims=" %%a in (%tmp_file%) do (
  set "line=%%a"
  call :check line
)

check.bat

setlocal EnableDelayedExpansion
set "var=!%1!"
echo(!var!
于 2012-11-19T14:38:14.753 回答
2

您修改后的 check.bat 中有多个问题

引号是一个状态机,因为第一个引号将引用语义打开,第二个关闭,第三个打开等。未引用(和未转义)>被解释为重定向输出的指令。

我对 check.bat 进行了大量修改,加入了一堆 ECHO 语句来提供正在发生的事情的叙述。您的原始代码作为所有大写字母嵌入我的版本中。

这是我修改后的版本的输出,我希望能解释为什么你会得到你的结果。在您尝试了解我修改后的 check.bat 如何产生此输出之前,我希望您阅读此输出。

"a"
---------------------------------------------
Executing: SET RAWINPUT=%1  which expands to  SET RAWINPUT="a"
Here is the result:
rawinput="a"

Executing: SET INPUT=%~1  which expands to  SET INPUT=a
Here is the result:
input=a

Executing: ECHO %1  which expands to  ECHO "a"
"a"

Executing: ECHO "%RAWINIPUT%"  which expands to  ECHO ""a""
""a""

Executing: ECHO "%INPUT%"  which expands to  ECHO "a"
"a"


"b -> b"
---------------------------------------------
Executing: SET RAWINPUT=%1  which expands to  SET RAWINPUT="b -> b"
Here is the result:
rawinput="b -> b"

Executing: SET INPUT=%~1  which expands to  SET INPUT=b -> b
Here is the result:
input=b -

Also created a file named "b" because the output of the command
is redirected. The file is empty because SET has no output.

 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of C:\Users\Public\utils

11/20/2012  09:30 AM                 0 b
               1 File(s)              0 bytes
               0 Dir(s)  316,104,765,440 bytes free

Executing: ECHO %1  which expands to  ECHO "b -> b"
"b -> b"

Executing: ECHO "%RAWINIPUT%"  which expands to  ECHO ""b -> b""

There is no screen output because output was redirected to file "b"
Here are the contents of "b":
""b -

Executing: ECHO "%INPUT%"  which expands to  ECHO "b -"
"b -"

这是我修改后的 check.bat,它产生了上面的输出。

setlocal enableDelayedExpansion
set value=%1
set "unquotedValue=%~1"

echo ---------------------------------------------
echo Executing: SET RAWINPUT=%%1  which expands to  SET RAWINPUT=!value!
SET RAWINPUT=%1
echo Here is the result:
set rawinput
echo.

echo Executing: SET INPUT=%%~1  which expands to  SET INPUT=!unquotedValue!
SET INPUT=%~1
echo Here is the result:
set input
if exist b (
  echo.
  echo Also created a file named "b" because the output of the command
  echo is redirected. The file is empty because SET has no output.
  echo.
  dir b
  del b
)
echo.

echo Executing: ECHO %%1  which expands to  ECHO !value!
ECHO %1
echo.

echo Executing: ECHO "%%RAWINIPUT%%"  which expands to  ECHO "!rawinput!"
ECHO "%RAWINPUT%"
if exist b (
  echo.
  echo There is no screen output because output was redirected to file "b"
  echo Here are the contents of "b":
  type b
  del b
)
echo.

echo Executing: ECHO "%%INPUT%%"  which expands to  ECHO "!input!"
ECHO "%INPUT%"
echo.


如果您不在 check.bat 中添加任何引号,则可以通过变量获得所需的结果

set rawinput=%1
echo %rawinput%

但是,如果您的原始文本文件包含自己的引号,那么一切都会崩溃。

这就是 jeb 建议将每一行存储在主程序中的变量中然后将变量名称传递给 check.bat 的原因。在 check.bat 中,您可以使用延迟扩展来安全地处理任何值,而不必担心引号或转义。

于 2012-11-20T14:45:44.720 回答