批量文件调用在for循环内转义重定向

时间:2012-11-19 14:25:28

标签: windows batch-file escaping

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

有没有办法告诉call转义此字符,还是在for循环的内容中替换它?

我查看了setlocal enabledelayedexpansion和(当通话更新为使用!时,它仍然无效。)

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.bat echo的%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.bat的{​​{1}}必须解释为:

b -> 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. 似乎没有表现出来,我们将不胜感激。

2 个答案:

答案 0 :(得分: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"这将扩展为
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!

答案 1 :(得分:2)

您修改后的check.bat

中存在多个问题

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

我通过输入一堆ECHO语句来大量修改check.bat,以提供正在发生的事情的叙述。您的原始代码作为所有CAPS嵌入我的版本中。

以下是我修改版本的输出,我希望能解释为什么你会得到你的结果。在您尝试了解我的修改后的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中,您可以使用延迟扩展来安全地处理任何值,而不必担心引号或转义。