中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [讨论]findstr的命令行分析机制
作者:
标题: [讨论]findstr的命令行分析机制 上一主题 | 下一主题
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『楼 主』:  [讨论]findstr的命令行分析机制

To All:

      问题缘起于bsijl一篇关于findstr错误过滤的主题[1],当时因为无法找到原因,所以只能推测 /g 开关存在某些问题。

      近日,因为编写一个debuger代码,再次使用了 findstr/g ,结果遇到了同样的问题[2]。经过仔细的测试[3]后,发现是 findstr 特殊的命令行分析机制所引起的问题。略述如下:

      1、findstr不同于早期的find,它对参数的排列有一定的要求,即遵循开关(可省略)、字符串(使用/c开关时省略)、文件名(可通配、可多个、有输入流时需省略)的顺序。

      2、开关可以使用引号,所以不能直接以与开关相同的关键字进行搜索;文件名含空格时必须用引号。

      3、搜索关键字的情况和表现就比较复杂,分述如下:
      3-1、无论是否使用开关/l或/r以及是否使用引号,关键字中的\都会成为转义字符,所以\\将成为\,\"将使引号失去字符串界定作用;
      3-2、搜索关键字可加或不加引号,当加引号时其中的\可能会再次转义。使用开关/l和/r时的转义结果可能会不同:当使用/r时,所以"\\\\"将成为单个\,"\\"将使关键字为空;当使用/l或均不使用时,"\\\\"和"\\"与单个\等价。
      3-3、如果关键字以单个\结尾,且无引号,则不会被转义;

      而 findstr/g出现的问题,应该与上述内容有关,但其内在机理仍无法透彻理解。不知各位有何高见?

[1]批处理删除XP输入法问题!请dos高手解决
http://www.cn-dos.net/forum/search.php?searchid=24472

[2]Test of findstr/v/g

  Quote:
E:\Batch\Test>set > envar.out

E:\Batch\Test>findstr /v /g:envar.out envar.out
LOGONSERVER=\\Test
ProgramFiles=C:\Program Files

E:\Batch\Test>findstr /v /i /g:envar.out envar.out
LOGONSERVER=\\Test

[3]Test of findstr
:: Test of findstr
:: Will Sort - 2006-06-10 - CMDWinXP
@echo off
cls&echo ---- "set>_tfs1.tmp & findstr /v /g:_tfs1.tmp _tfs1.tmp"
set>_tfs1.tmp & findstr /v /g:_tfs1.tmp _tfs1.tmp
pause

echo ---- "findstr /v /i /g:_tfs1.tmp _tfs1.tmp"
findstr /v /i /g:_tfs1.tmp _tfs1.tmp
pause

echo ---- "sort /r _tfs1.tmp > _tfs2.tmp & findstr /v /g:_tfs1.tmp _tfs2.tmp"
sort /r _tfs1.tmp > _tfs2.tmp & findstr /v /g:_tfs1.tmp _tfs2.tmp
pause

echo ---- "set|findstr /v /g:_tfs1.tmp"
set|findstr /v /g:_tfs1.tmp
pause

cls&echo ---- "dir C:\ /w > _tfs2.tmp & findstr /v /g:_tfs2.tmp _tfs2.tmp"
dir C:\ /w > _tfs2.tmp & findstr /v /g:_tfs2.tmp _tfs2.tmp
pause

echo ---- "echo :\ > _tfs2.tmp & findstr /v /g:_tfs2.tmp _tfs2.tmp"
echo :\ > _tfs2.tmp & findstr /v /g:_tfs2.tmp _tfs2.tmp
pause

cls&echo ---- "findstr /g:_tfs1.tmp _tfs1.tmp>_tfs2.tmp & fc _tfs1.tmp _tfs2.tmp"
findstr /g:_tfs1.tmp _tfs1.tmp>_tfs2.tmp & fc _tfs1.tmp _tfs2.tmp
pause

cls&echo ---- "set|findstr /r "\\\\  \\\\""
set|findstr /r "\\\\  \\\\"
pause

echo ---- "set|findstr /l "\\\\  \\\\""
set|findstr /l "\\\\  \\\\"
pause

cls&echo ---- "echo _tfs1_tmp > _tfs1.tmp & findstr "/l" "_tfs1.tmp" "_tfs1.tmp""
echo _tfs1_tmp >> _tfs1.tmp & findstr "_tfs1.tmp" "_tfs1.tmp"
pause
del _tfs?.tmp
[ Last edited by willsort on 2006-6-11 at 18:38 ]



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2006-6-10 22:46
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
Climbing
铂金会员

网络独行侠


积分 6962
发帖 2753
注册 2003-4-16
来自 河北保定
状态 离线
『第 2 楼』:  

在我的XP上这个结果如何解释?

d:\work>findstr /v /g:envar.out envar.out
FINDSTR: 搜索字符串太长。

d:\work>findstr /v /g:envar.out envar.out
FINDSTR: 搜索字符串太长。

d:\work>findstr /v /g:envar.out
FINDSTR: 搜索字符串太长。



偶只喜欢回答那些标题和描述都很清晰的帖子!
如想解决问题,请认真学习“这个帖子”和“这个帖子”并努力遵守,如果可能,请告诉更多的人!
2006-6-11 01:18
查看资料  发送邮件  访问主页  发短消息 网志  OICQ (653668)  编辑帖子  回复  引用回复
无奈何
荣誉版主





积分 1338
发帖 356
注册 2005-7-15
状态 离线
『第 3 楼』:  

在我的 XP 下和 willsort 兄 3、的描述相同。这个恼人的结果不知道能不能确定是 FINDSTR 的 BUG ,请朋友们多试一下其它系统的情况。看来关键字中含有 “\” 字符应该多加小心了。



  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

2006-6-11 03:02
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子  回复  引用回复
3742668
荣誉版主





积分 2013
发帖 718
注册 2006-2-18
状态 离线
『第 4 楼』:  

唔,似乎只有当\后面的字符为非字母和非数字的时候才会出错。感觉microsoft准备把findstr做成cmd下的正则表达式工具似的,但是又没有考虑到与其他参数之间的兼容性,导致最后的结果是画虎不成反类犬。
另外在某些时候,findstr的查找字符串中包含中文时,需要加上/i参数才能避免错误,具体环境以及代码已忘,或许findstr除了正则表达式方面的bug外还存在unicode与ascii转换的bug。

2006-6-11 14:43
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 5 楼』:  

Re Ups:

    另外一个问题:

    因为开关也允许引号,所以无法以 "/l" 或 "/r" 等与开关相同的文本串作为关键字匹配,下面的句式将会出错:
        echo /l /r > test
        findstr /l "/r" test

    不过,可以使用开关 /c 来强制指定关键字:
        findstr /l /c:"/r" test
        findstr /l /c:/r test

    还有一个方法,就是上文提到的 \ 了:
        findstr /l \/r test
      
    此外,这个 \ 还可以让我们的关键字中包含引号:
        echo /l /r >test
        echo "/r" >> test
        findstr /l \"/r\" test

    最后,修订和增补顶楼3-2中的一些描述:
        3-2、开关/r和开关/l相同,其后的关键字均可使用或不使用引号;使用引号时:
        3-2-1、"\"和"\\\"等价于引号和其后各个串所各自代表的多个关键字;
        3-2-2、"\\\\\"和"\\\\\\\"等价于引号加\组成的关键字和其他多个关键字;
        3-2-3、"\\\\\\\\\"等价于引号加\\组成的关键字和其他多个关键字;
        3-2-4、"\ ","\\","\\\ ","\\\\\ ","\\\\\\","\\\\\\\ "等价于空;
        3-2-5、"\\ ","\\\\"等价于一个\;
        3-2-6、"\\\\ ","\\\\\\\\"等价于两个\;
        3-2-7、"\\\\\\ "等价于三个\;
        3-2-8、"\\\\\\\\ "等价于四个\;

    以上数据由以下方法测得,测试文件见[1][2],当不使用/r开关与使用开关/l相同,;
        type test1.txt | findstr /r "test_key" test2.xt


[1] Test text of findstr - "test1.txt"

  Quote:
/l /r
"/l"
" test1
\" test1
\\" test1
\\\" test1
\\\\" test1
\ test1
\\ test1
\\\ test1
\\\\ test1

[2] Test text of findstr - "test2.txt"

  Quote:
" test2
\" test2
\\" test2
\\\" test2
\\\\" test2
\ test2
\\ test2
\\\ test2
\\\\ test2

[ Last edited by willsort on 2006-6-11 at 18:25 ]



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2006-6-11 18:24
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
220110
荣誉版主




积分 718
发帖 313
注册 2005-9-26
状态 离线
『第 6 楼』:  



  Quote:
        3-2、开关/r和开关/l相同,其后的关键字均可使用或不使用引号;使用引号时:
        3-2-1、"\"和"\\\"等价于引号和其后各个串所各自代表的多个关键字;
        3-2-2、"\\\\\"和"\\\\\\\"等价于引号加\组成的关键字和其他多个关键字;
        3-2-3、"\\\\\\\\\"等价于引号加\\组成的关键字和其他多个关键字;
        3-2-4、"\ ","\\","\\\ ","\\\\\ ","\\\\\\","\\\\\\\ "等价于空;
        3-2-5、"\\ ","\\\\"等价于一个\;
        3-2-6、"\\\\ ","\\\\\\\\"等价于两个\;
        3-2-7、"\\\\\\ "等价于三个\;
        3-2-8、"\\\\\\\\ "等价于四个\;

我早前也发现这规律存在路径名上,只是没深入研究,没敢贴上来.
我是从"dir .\",  " dir ..\" 开始,大家不妨测试下.

2006-6-17 21:07
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 7 楼』:  

Re 220110:

      UNC 路径名中 \ 的解析与 findstr 关键字是不同的,它只有界定目录的作用,而没有转义字符的作用。



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2006-6-18 18:19
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
jackerloo2009
新手上路





积分 1
发帖 1
注册 2009-5-19
状态 离线
『第 8 楼』:  

echo 王志慧|findstr /i ".*净"
加/i 仍然是个错误

还有对于/l参数仍不明了

findstr /v /x /i /g:B.txt A.txt
findstr /v /x /i /g:A.txt B.txt

我曾经比较过两个文本,里面都是邮件地址,结果不加/l的话结果中出来了一个共同点

两个文本中都有这个地址 p*.tournois@chello.fr

但比较不同后的结果仍然还是有这个地址。但是加了/l后避免了,对于这个/l按字使用搜索字符串,如何理解?所有的都变成普通字符逐字比较?

2009-6-27 00:18
查看资料  发送邮件  发短消息 网志  OICQ (282944445)  编辑帖子  回复  引用回复
echoair
新手上路





积分 8
发帖 33
注册 2009-11-10
状态 离线
『第 9 楼』:  

希望大家能把findstr的基本用法系统做个总结…

2009-11-11 13:04
查看资料  发送邮件  发短消息 网志  OICQ (39820396)  编辑帖子  回复  引用回复
hongcheng668
新手上路





积分 10
发帖 9
注册 2009-10-17
状态 离线
『第 10 楼』:  

不错 学习了

2009-11-16 15:43
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hongcheng668
新手上路





积分 10
发帖 9
注册 2009-10-17
状态 离线
『第 11 楼』:  

呵呵 厉害

2009-11-16 15:43
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hongcheng668
新手上路





积分 10
发帖 9
注册 2009-10-17
状态 离线
『第 12 楼』:  

能不能详细点

2009-11-16 15:43
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: