bat(批处理)处理特殊符号(感叹号,百分号)等

您找遍全网可能都找不到的解决方案

1 背景

最近迷恋上了bat脚本,以前没这么深入用,对它没啥感情。但是最近是近乎疯狂的迷上了它。

但是越是用的深入,越是发现各种稀奇古怪的事情:

就比如对特殊符号的处理,比如想要替换字符串里头的感叹号和百分号,死活就是成功不了。

而这类的功能换用javaScript/java/python都会非常简单。

没办法,总不能因为人家有弱点,我就弃用吧!

所以死磕开始...

2 问题描述

要替换的内容在txt文件里头(替换的字符串不包含特殊符号),然后逐行读取的时候,我开启了变量延迟,然后呢,替换之后,发现txt里头原本有的特殊符号!丢失了。查了下因为!是变量延迟开启时候的特殊符号。

于是我关闭了变量延迟使用call 的变量延迟的实现方案,但是这个时候又出错了,因为我的文本里头有><这类标签的符号,查了下这类也是特殊符号,要用需要转义。

综上,奔溃呀!!!

所以稍微总结下:

使用!var!这种变量延迟,可以解决除了!特殊符号外的所有特殊符号,

而使用call 这种变量延迟,可以解决!特殊符号。

另外有一个前提,就是要替换的内容肯定不会和!同行。

所以其实要做的就简单了。只要逐行判断是否有!,如果有,就跳过,不替换。如果没有,就开启!var!模式的变量延迟,就替换。但是,判断某一行有没有!,就是我在为期三天的排查过程的瓶颈了。找不到可用的。

市面上能找得到的解决方案都是通过echo %var% | findstr....

但是这种模式会导致findstr之前,就让var里头的感叹号丢失了。

3 处理字符串里头的!%等特殊符号

笔者也是翻看了全网的很多资料。但是在我把全网翻个底朝天之前,在一个疙瘩角落里头找到了一个曲线救国的方案。

既然通过echo %var% | findstr....行不通。

但是通过findStr直接读取文本文件是不会有问题的。

所以作者采用逐行读取文本内容,然后读取之后,将当前行写入到一个临时文件里头,再采用findstr来判断是否有!:

@echo off
Setlocal enableDelayedExpansion

rem 逐行读取
for /f  "delims=" %%i in (a.txt) do (
	rem 判断当前行是否包含有特殊符号% !
	rem 第一步先写入到文件里头
	echo %%i > special.tmp
	rem 第二步通过文件来判断
	call :hasSpecialWord
	if "!specialWordNo!"=="" (
		echo 不存在特殊符号
	)^
	else (
		echo 存在特殊符号!specialWordNo!
	)
)
pause

rem 判断是否含有% !  特殊符号只要被进行赋值等之类操作,都会没掉,因此只能只能通过文件来处理
:hasSpecialWord
for /f "delims=:" %%a in ('findstr /n "%% ^!" special.tmp') do set specialWordNo=%%a
goto end

:end

上面的demo成功之后,就开始解决前面的背景问题:

@echo off
rem 案例要求:对a.txt进行如下操作: 替换里头的xml为wlt,a.txt里头包含有%和!
Setlocal enableDelayedExpansion

rem 创建一个空白文件
1 2>nul > a.txt.bak
for /f  "delims=" %%i in (a.txt) do (
	rem 每次循环前,先开启变量延迟
	Setlocal enableDelayedExpansion
	rem 判断当前行是否包含有特殊符号% !
	rem 第一步先写入到文件里头
	echo %%i > special.tmp
	rem 第二步通过文件来判断
	call :hasSpecialWord
	if "!specialWordNo!"=="" (
		set tmp=%%i
		set tmp=!tmp:xml=wlt!
		echo !tmp! >> a.txt.bak
	)^
	else (
		rem 当含有特殊符号的时候,关闭变量延迟
		Setlocal disableDelayedExpansion
		echo %%i >> a.txt.bak
	)
)
del a.txt
ren a.txt.bak a.txt

echo 总结:
echo 开启变量延迟 直接输出会丢失感叹号
echo 关闭变量延迟 直接输出可以全部保留
echo 开启变量延迟 变量替换操作在变量含有感叹号的时候会出错
echo 关闭变量延迟 变量替换操作在变量含有左尖括号或者右尖括号时会出错
pause

rem 特殊符号只要被进行赋值等之类操作,都会没掉,因此只能只能通过文件来处理
:hasSpecialWord
for /f "delims=:" %%a in ('findstr /n "%% ^!" special.tmp') do set specialWordNo=%%a
goto end

:end


附上代码里头使用的a.txt:

<xml></xml>
a=1%
b!!!!=null<wlt></wlt>

运行代码后得到a.txt为:

<wlt></wlt> 
a=1% 
b!!!!=null<wlt></wlt> 

赠送给新一代农民工:每天学习一点点,天天发现新大陆

20220722更新

应读者要求,将评论区的内容更新到这边:

读者遇到一个问题:

<a>
<!--This is a test file -->
17302 xml
</a>
转完就变成了
<a>
<--This is a test file -->
17302 wlt
</a>

我提出了一个解决方案:

@echo off 
setlocal enabledelayedexpansion
rem 清空1.bak
1 2>nul > 1.bak 
for /f "delims=" %%i in (c.txt) do ( 
    setlocal disabledelayedexpansion
    rem 如果包含感叹号,就写入1.bak
    echo "%%i" | findstr "!" >nul &&( echo %%i >> 1.bak ) || ( 
        endlocal 
        setlocal enabledelayedexpansion 
        set tmpFileContent=%%i 
        set tmpFileContent=tmpFileContent:xml=wlt! 
        echo !tmpFileContent! >> 1.bak 
    ) 
    endlocal 
)

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独行侠_阿涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值