在Windows批处理文件中将反斜杠改为正斜杠

46

我试图将一个包含文件名和位置的变量中所有反斜杠()转换为正斜杠(/)。我已经阅读过相关资料,看到了:

%variable:str1=str2%

set "var=%var:\=/%"

我已经尝试过,但显然做得不对。

这是我.bat脚本中相关的部分:

FOR %%f IN ("E:\myfiles\app1\data\*.csv") DO (
  echo %%f  
  set "f=%%f:\=/%"
  echo %%f  
  echo.                 
)
输出显示每个文件名都列出了两次。 即,这一行:
set "f=f:\=/%"

它没有做我想要的事情。有人能看出我做错了什么吗?


抱歉,你是对的。我的意思是BATCH - 用%20替换文件名中的空格以供curl使用 - jeb
5个回答

106

这将把变量中的反斜线更改为正斜线:

set "variable=E:\myfiles\app1\data\*.csv"
set "variable=%variable:\=/%"
echo "%variable%"

2
这个答案完全可以正常工作,不需要循环。我刚刚自己试过了(虽然我不需要引号)。 - ThePersonWithoutC
4
谢谢@ThePersonWithoutC - 引号保护某些有毒字符,例如&,并使其在不寻常情况下更加健壮。 - foxidrive
1
谢谢,这里是最好的解决方案。 - CodeMonkey
1
如何在控制台中直接执行相同的操作? - Elie G.
1
@ElieG。上述代码在控制台中直接运行良好。 - tresf

26
在一个代码块语句中,整个代码块会被解析后再执行。在代码块中的任何 %var% 都将被替换为代码块解析时该变量的值(在代码块执行之前) - 对于 FOR ... DO (block) 同样适用。
因此,IF (something) else (somethingelse) 会使用遇到 IF 时的 %variables% 值来执行。
克服这点常见的方法有两种:1)使用 setlocal enabledelayedexpansion 并使用 !var! 替代 %var% 来访问更改后的 var 值;2)调用子程序以使用更改后的值进行进一步处理。
注意使用 CALL ECHO %%var%% 显示更改后的 var 值。
你的代码包含两个名为 f 的不同变量。
第一个是循环控制“元变量”称为 f,可以通过 %%f 引用。
第二个是由 set "f=..." 语句建立的普通环境变量 f。可以使用 %f% 访问此变量,但在代码块内,它似乎保留了控制 for 解析时的值(实际上,任何 %var% 在解析时都被替换为该变量在那个时间的值)。 metavariables 不能用于字符串操作语句,例如子字符串或替换,只能使用普通环境变量来执行这些操作,因此需要将元变量 f 的值分配给环境变量 f,然后对环境变量 f 执行字符串替换任务。 当然,关键是必须使用 delayedexpansion!var! 语法在块内访问修改后的环境变量的值。
因此,
setlocal enabledelayedexpansion
for...%%f...do (
  echo %%f
  set "f=%%f"
  set "f=!f:\=/!"
  echo !f!
)
echo just for demonstration %f% !f! %%f

这以所需方式设置了f的值(当然,您始终可以更改名称以避免混淆...)

最后一行仅用于显示通过f获取的最终值可以作为%f%!f!在循环外部访问,而%%f是超出上下文范围并显示为%f

另一种无需使用delayedexpansion的方法是

for...%%f...do (
  echo %%f
  set "f=%%f"
  call set "f=%%f:\=/%%"
  call echo %%f%%
)
echo just for demonstration %f% !f! %%f

不同之处在于使用call命令并将%符号翻倍,最后一行将显示!f!,作为一个字面值。因为在delayedexpansion模式之外,!只是另一个没有特殊含义的字符。


1
哇,非常全面的解释,非常感谢!我不得不读几遍,但我觉得我懂了..!! Windows批处理脚本对我来说仍然看起来非常奇怪,我不确定我是否真的会“理解它”。 - user3253319
我实际上需要做相反的操作:将正斜杠替换为反斜杠,但是你的解释非常完美。 - Jesse Chisholm
如何直接在控制台中执行相同的操作? - Elie G.

5
这对我来说似乎有效:
echo off

setlocal enabledelayedexpansion

FOR %%f IN ("C:\tools\workspace\*") DO (
  set old=%%f
  echo !old!
  set new=!old:\=/!
  echo !new!  
  echo.                 
)

使用单独的变量而不是循环变量会有所不同,同时启用延迟扩展,因为使用循环变量 %%f 的变量替换语法好像不起作用。

2

Magoo的有用回答展示了如何在for循环的(...)块内执行动态替换(通过延迟扩展)。

foxidrive的回答展示了在变量值中执行字面上的全局字符串替换的一般cmd语法(在问题中也简要显示)。

让我补充这些答案,提供一个使用PowerShell's CLI的解决方案:

注意:

  • 在这个简单的例子中,这种做法过度了,并且比纯的cmd解决方案性能更差。

  • 但是,如果您需要使用PowerShell的基于正则表达式的-replace操作符进行更复杂的字符串替换,这种技术可能会很有帮助。

@echo off

:: Sample path.
Set inPath=C:\foo\bar

for /f "usebackq delims=" %%i in (
  `powershell -noprofile -c "\"%inPath%\" -replace '\\', '/'"`
) do set "outPath=%%i"

echo %outPath%

以上产生了以下结果:
C:/foo/bar

内联变量,输入路径直接嵌入并直接输出转换后的字符串:

C:\>powershell -noprofile -c "\"C:\foo\bar\" -replace '\\', '/'"
C:/foo/bar

-1

以下代码可将 Windows 系统中的反斜杠转换为正斜杠:

 typedef std::basic_string<TCHAR> tstring;
 tstring pathbasic = tstring(programdata) + _T("\\myfile.txt");
 std::replace(pathbasic.begin(), pathbasic.end(), _T('\\'), _T('/'));

2
这个答案与批处理文件无关。 - Shiraz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接