批处理脚本中如何替换字符串中的字符

20

我需要用批处理脚本从字符串中删除字符*,该字符串类似于:
*10.*31.**2.*65

我想要删除这个字符串中的所有*


注意:*是一个特殊字符,因此您无法使用%var:a = b%语法。 - mwfearnley
7个回答

48

您可以将移除过程简化为一行。例如,如果我有一个类似这样的字符串:

set string=hello!

如果我想要去掉这个字符串中的 "!",我可以这样做:

set string=%string:!=%

字符串现在的值将为"hello",而不是"hello!"

编辑:jeb在评论中指出,您无法使用此方法替换"*"。这是因为*是用于批处理文件模式匹配的通配符字符(对此的精彩解释在这里)。我在发布此答案时并不知道这一点,因为我认为此替换方法适用于所有输入字符串。如果您特别需要替换*,我建议遵循magoo的答案。否则,我将继续保留此答案,供那些需要批量字符串替换的通用、简短的一行解决方案使用。


4
这不是对问题的答案,因为你不能用这种方法替换 *。因为以 * 开头的替换表达式具有特殊含义。 - jeb
1
将1.2.3.4转换为1,2,3,4。 setlocal集合string = 1.2.3.4 set string =%string:.=,% - Justin
1
这里使用语法 %variable:StrToFind=NewStr%,请参考 https://ss64.com/nt/syntax-replace.html。 - Wayne Uroda

9
@ECHO OFF
SETLOCAL
SET mystring=*10.31.*2.*65
:deaster
FOR /f "tokens=1* delims=*" %%i IN ("%mystring%") DO (
   SET mystring=%%j
   IF DEFINED mystring (
      SET mystring=%%i%%j
      GOTO deaster
   ) ELSE (
      SET mystring=%%i
   )
)
ECHO result=%mystring%=

4

您不需要整个脚本来完成此操作。您只需要一个单独的 for /f 循环即可。

C:\Users\rojo>set test=*10.*31.**2.*65

C:\Users\rojo>echo %test%
*10.*31.**2.*65

C:\Users\rojo>for /f "tokens=1-4 delims=.^*" %I in ("%test%") do @set test=%I.%J.%K.%L

C:\Users\rojo>echo %test%
10.31.2.65

如果您想将for循环放入批处理脚本中,请使用%%I%%J%%K%%L代替单个百分号。


2
解决上述问题的另一种方法是在批处理脚本中使用PowerShell的replace命令。
set var=*10.*31.*2.*65
echo %var%>var.txt && powershell -command "(get-content var.txt) -replace '[\x2A]+', '' | set-content var.txt"
set /p var=<var.txt
echo %var%

在上述代码中,第二行:
  • 将您的字符串写入文本文件
  • 调用 PowerShell 命令获取该文件的内容
  • 用 null 替换 * 字符
  • 用新值覆盖文本文件
完成后,您将读取变量中的值。
进一步解释 replace 命令,第一个单引号是您要搜索的内容。我们使用方括号来标识 * 字符作为 十六进制字符(\x2A 是 * 的十六进制值)。逗号后,第二组单引号不包含任何值,以便删除搜索对象。
另一个选项是使用插入符号来搜索除了方括号中标识的内容之外的所有内容。这将删除除所需内容之外的所有内容。要执行此操作,您可以将第二行替换为:
echo %var%>var.txt && powershell -command "(get-content var.txt) -replace '[^\x30-x39\x2E]+', '' | set-content var.txt"

第一组字符\x-30-x39表示0-9。而\x2E则代表句点“。”。
当您完成文本文件后,请输入一行以删除它。
if exist var.txt del var.txt

我从来没有见过这种结构 command1 > file | command2。 这有什么特别之处吗?&&|更好吗? - mwfearnley
感谢 @mwfearnley。你是正确的。&& 是正确的选择。&& 意味着在第一个命令成功后执行第二个命令。管道将第一个命令的输出发送到第二个命令中使用。我已更新该行以使用 &&。 - David

1
@echo off
setlocal EnableDelayedExpansion

set "str=*10.*31.**2.*65"

set "char=" & set "repl=" & set "loc=0"

echo !str!

call :replace

echo !repl!

exit /b

:replace
  set "char=!str:~%loc%,1!
  if "!char!" == "" exit /b
  if "!char!" equ "*" set "char=_"
  set "repl=!repl!!char!"
  set /a "loc+=1"
goto :replace

endlocal

这是另一种解决方案。可能会慢一些,但调用set的速度太慢了。

0

这段代码将a替换为b字符:

Set search=%search:a=b%

即使问题的第一个评论已经显示了这一点,并解释了为什么它不能在这里用于 * - jeb

-1

看看sed,这是一个流编辑器。如果你使用的是Windows(假设你是),你可以在网上找到预编译的二进制文件。

echo "*10.31.*2.*65" | sed 's/\*//g'

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