Board logo

标题: [文本处理] [已解決]批处理如何查找指令里的百分号或感叹号字符串? [打印本页]

作者: strong12345    时间: 2009-8-19 02:56     标题: [已解決]批处理如何查找指令里的百分号或感叹号字符串?

举个例子
例如我想查找 echo %var% 这指令里,有没有存在%字?
  1. @echo off
  2. echo echo %var%|findstr "%%" && (echo .有%%符号)
  3. pause
复制代码
可是这样的话,再一开始的 %var% 时,%var%已经被替换成变量值了,这样就无法测得有无%符号
我知道这个例子是可以直接用转义来修改他

但是小弟现在的问题是,要判断很多不确定的随机指令

例如有个123.txt文件
  1. @echo off
  2. echo %hahahaha%
  3. echo hahahaha
  4. echo %var%
  5. echo var
复制代码
2,4行都有用到%,那就能侦测输出说 2,4行含有%字元

[ 本帖最后由 strong12345 于 2009-8-20 17:56 编辑 ]
作者: strong12345    时间: 2009-8-19 08:37

我發現找 "%" 問題是小 , 但是就是找不了  "!"
保存為文件123.txt
  1. @echo off
  2. echo %var%
  3. echo !var!
  4. pause
复制代码
例子1︰找% (成功)
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%a in ('type 123.txt') do (
  4. echo %%a|findstr "%%">nul && (echo yes)
  5. echo %%a|findstr "%%">nul || (echo no)
  6. )
  7. pause
  8. exit
复制代码
例子2︰找! (失敗...)
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%a in ('type 123.txt') do (
  4. echo %%a|findstr "\!">nul && (echo yes)
  5. echo %%a|findstr "\!">nul || (echo no)
  6. )
  7. pause
  8. exit
复制代码

[ 本帖最后由 strong12345 于 2009-8-19 08:39 编辑 ]
作者: terse    时间: 2009-8-19 09:38

这里变量延迟可以不打开
作者: strong12345    时间: 2009-8-19 09:53

......可是小弟的程序,之前必须用到很多变量延迟....
在此指令前先关闭变量延迟,执行完后再打开吗??
作者: Lumiere    时间: 2009-8-19 10:07     标题: 回复 4楼 的帖子

个人觉得找!最好在关闭延迟的情况下。
作者: zqz0012005    时间: 2009-8-19 10:21

  1. @echo off
  2. rem if here, echo lines including %% and ! are:
  3. setlocal enabledelayedexpansion
  4. echo 包含%%和^^^!的行:
  5. for /f "delims=:" %%a in ('findstr /n "%% ^!" 123.txt') do echo %%a
  6. pause
复制代码

作者: strong12345    时间: 2009-8-19 12:10

请问版主 findstr /n 参数的意义是什么?
我在findstr /? 里并没有看到 /n 参数的介绍?
作者: strong12345    时间: 2009-8-19 12:50

小弟改成 查找前先 setlocal disabledelayedexpansion
查找后再 setlocal enabledelayedexpansion
这样真的就可以了

另外再查找 ! 时,小弟用 ^! 转义不行,要用 \! 才行....
作者: Lumiere    时间: 2009-8-19 12:53     标题: 回复 6楼 的帖子

为什么在引号里出现!只需要一个^呢?有感叹号不是需要预处理两次的么?
作者: Batcher    时间: 2009-8-19 13:26     标题: 回复 7楼 的帖子

你用的什么操作系统?
  /N         Prints the line number before each line that matches.

作者: zqz0012005    时间: 2009-8-19 14:00     标题: 回复 9楼 的帖子

开启变量延迟后要得到字符!,则要求在预处理后得到的是^!,以便再次处理时让^对!进行转义,因此可以使用以下几种形式:
echo ^^!
echo ^^^!
echo "^!"

第二句中!前面的^是对一个普通字符(预处理时!的确只是普通字符)进行转义,使它变得“更加普通”,虽然没必要,但没什么影响(而且还能以防万一后面是个特殊字符)。类似echo ^h^i,只要你喜欢。

在引号中,预处理时^会失去转义作用。因为"本身有转义作用,会使其中的特殊字符失去特殊性。


再如开启变量延迟后检验闰年:
setlocal enabledelayedexpansion
set year=1900
set /a "isleap = ^!(%year% %% 400) | ^!(%year% %% 4) & ^!^!(%year% %% 100)"
if !isleap!==1 (each %year% is leap year^^!) else echo n
作者: Lumiere    时间: 2009-8-19 15:32     标题: 回复 11楼 的帖子

这个都理解,问题是在楼主自己个的代码之上换成
  1. echo %%a|findstr ^^! 2>nul && echo yes
复制代码
为什么不行呢?还有我试过"^!",^^^^!都不行,不知道为什么。
作者: zqz0012005    时间: 2009-8-19 16:21     标题: 回复 12楼 的帖子

开启变量延迟后对for的变量%%i也会进行再次处理,见此帖:
http://www.bathome.net/viewthread.php?tid=4580

另外,echo %%a|findstr 这种方式本身存在隐患,如果%%a中包含特殊字符会产生问题。
作者: Lumiere    时间: 2009-8-20 00:01

这个两次处理我考虑到了,但是还是不行,不知道为什么。
作者: zqz0012005    时间: 2009-8-20 00:17

echo %%a|findstr (且不说其他特殊字符带来的问题)
开启变量延迟后,echo %%a 的结果基本不会包含“!”(情况特殊时还是有可能),叫findstr到哪里去找?(那个链接不知道你看没有)
作者: Lumiere    时间: 2009-8-22 10:47     标题: 回复 15楼 的帖子

多谢版主,那个连接我看了,不过有些迷惑。文本123.txt还是楼主原来的内容,看如下代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (123.txt) do (
  3.     echo %%a|findstr ^^^^! 2>nul && echo yes
  4.     echo %%a|findstr ^^^^! 2>nul || echo no
  5. )
  6. pause
复制代码
结果输出为
  1. @echo off
  2. yes
  3. @echo off
  4. echo %var%
  5. yes
  6. echo %var%
  7. echo
  8. yes
  9. echo
  10. pause
  11. yes
  12. pause
  13. 请按任意键继续. . .
复制代码

这里从结果来看,%%a确实经过了两次处理,因为第三行的!var!为空,一定是扩展了。但是既然这样的话,第二行的%var%也应该会被处理,被扩展才对啊,应该也会显示为空,显示结果应该不会在加%var%才对啊。这里是一个问题。再看如下代码:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (123.txt) do (
  3.     echo %%a|findstr ^^^! 2>nul && echo yes
  4.     echo %%a|findstr ^^^! 2>nul || echo no
  5. )
  6. pause
复制代码
只在findstr后面少写了一个^结果就变成
  1. no
  2. no
  3. no
  4. no
  5. 请按任意键继续. . .
复制代码
这里一个^的差别怎么会这样呢?第一段代码解释为何会先显示文本里的内容而第二段不会呢?我试过了,第一段代码经过第一次预处理之后会将命令解释为findstr ^^!。第二次过后就变成查找字符^,我也验证过,无论什么字符串不管有无^用findstr查找结果都是找得到这做何解释?
我想,既然含有!需要两次处理,而在!!型变量先处理特殊字符,后扩展,而且扩展以后就原样输出,那么我尝试将%%a改成!!型,特码如下:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (123.txt) do (
  3.     set "var=%%a"
  4.     echo !var!|findstr ^^^! 2>nul && echo yes
  5.     echo !var!|findstr ^^^! 2>nul || echo no
  6. )
  7. pause
复制代码
这样我想,!var!变量扩展就会延迟,先第一次预处理处理完特殊字符^,第二次处理的时候就直接查找!,正好这时候!var!也扩展,那么扩展以后!var!本身含有的不管是%还是!都不会再次处理了,但是显示结果仍然清一色no. 麻烦版主再指点一下了,这些问题真的比较伤脑筋。

[ 本帖最后由 Lumiere 于 2009-8-22 10:51 编辑 ]
作者: zqz0012005    时间: 2009-8-22 12:32

说明那个链接你还没有完全消化。
在你set "var=%%a"时,%%a中的!就消失了,即变量var的值里面已经没有!了。

echo %%a|findstr ^^^^!
这个的最终意思是echo %%a|findstr "^",即匹配行首位置(结果会显示该行内容)。
原因我不再赘述了,结合我前面讲的不难理解。
所以开启变量延迟后要查找行首的!字符,要写成
findstr ^^^^^^!    findstr ^^^^^^^!
findstr "^^^!"
findstr /b ^^!    findstr /b ^^^!
findstr /b "^!"
作者: Lumiere    时间: 2009-8-22 16:00     标题: 回复 17楼 的帖子

多谢斑竹提点。现在显示结果为什么会清一色no我明白了。不过在此还有3小问题。第一,echo %%a|findstr ^^^^!,预处理后查找^,就是匹配行首,但是为什么会显示两次行内容呢?
第二,这说,如果想要查找文本中的字符^,那不是做不到了么?因为findstr会将其匹配行首。对么?
第三,为什么有一行会是echo %var%呢,在预处理的时候%var%应该也要扩展为空才对啊。

[ 本帖最后由 Lumiere 于 2009-8-22 16:03 编辑 ]
作者: zqz0012005    时间: 2009-8-22 19:45

1、因为你有两次echo,虽有2>nul但没有1>nul,两次都能找到匹配。

2、不要忘了findstr的转义符\

3、注意我前面的说法是再次处理,而不是再次处理。处理!那一次跟预处理是不同的,简单来说,这次只处理!和^(其实^算是被“拖累”的)。
作者: Lumiere    时间: 2009-8-23 11:32     标题: 回复 19楼 的帖子

再次感谢斑竹不厌其烦回帖。前两个问题解决了,一语惊醒梦中人啊,乖自己太粗心,应该很容易想到的。不过第三点小弟还有些迷惑。就算照斑竹的意思,第一次预处理只判断语法,处理特殊字符,扩展%%型变量,第二次才处理!还有^,可echo %%a部分%%a里面包含有%var%这样的变量,在预处理的时候就应该要别扩展才对啊,不是么?
作者: zqz0012005    时间: 2009-8-23 11:57

预处理时是将%%a变成%a,这里根本没有出现%var%,它是for展开后才有的,但这时已是预处理之后。

看楼主似乎在“预处理”这个话题上纠结了很久?其实verybat上的相关帖子加起来,足以理解。虽然那些帖子比较零散且有重复,知识讲解不够系统,有些地方不够详尽或有纰漏,但自己稍加整理,多在实际中体会,还是不难掌握的。
作者: Lumiere    时间: 2009-8-23 12:04     标题: 回复 21楼 的帖子

呵呵,多谢斑竹,你虽然很牛,可是还是有个小错误。这个帖子我可不是楼主喔?呵呵,我喧宾夺主了,不好意思,在这里道个歉,斑竹你太可爱了,哈哈……
其实后来我自己去验证了,我的想法也正和你解释一样,因为除了这样也没其他的解释了。我自己写代码验证了,%%a也是变量,也需要扩展,也需要先预处理变为%a,所以里面包含的%var%在预处理后会直接输出。我开始一直不将%%a当成变量。现在明白了。再次感谢,加料……
作者: Lumiere    时间: 2009-8-23 12:07     标题: 回复 21楼 的帖子

不管是verybat还是bathome,关于预处理的帖子确实很多,各位达人也讲得很透彻,只不过确实有些凌乱和重复,有时候让人看了会小有烦躁,而且本身同样的文章不同的人看起来理解的思路会不一样,有些人愿意钻牛角尖,有些人就大而化之。所以这还是需要经过一番练习,推敲,在实际练习中发现问题并解决问题,这样才能不断提高,光看别人的陈述,是不会有实质性提升的,就算能记住些东西也容易忘记。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2