findstr的命令行分析机制

来源:http://www.cn-dos.net/forum/viewthread.php?tid=21167&fpage=1&highlight=findstr

willsort
版主

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
CODE: [Copy to clipboard]

:: 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 ]

Climbing
金牌会员

『第 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: 搜索字符串太长。

无奈何
版主

『第 3 楼』:

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

3742668
版主

状态 离线 『第 4 楼』:

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

willsort
版主

状态 离线 『第 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 ]

220110
版主

状态 离线 『第 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 ..\" 开始,大家不妨测试下.

willsort
版主

状态 离线 『第 7 楼』:

Re 220110:

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

另外,findstr /v ^%var%$ test.txt 语句中,如果test.txt最后一行就是要匹配的%var%,且该行不为空,则不能过滤最后一行的内容,似乎是分行标志识别出了错

原文地址:https://www.cnblogs.com/sfqas/p/12181862.html

时间: 2024-07-30 09:26:26

findstr的命令行分析机制的相关文章

命令行分析java线程CPU占用

1.使用top命令找出占用cpu最高的JAVA进程pid号 2. 找出占用cpu最高的线程: top -Hp pid  -d 1 -n 1 3. 打印占CPU最高JAVA进程pid的堆栈信息 jstack pid > /tmp/stacktrace.log 4. 把占CPU最高线程号码换算成16进制到stacktrace.log中寻找对应线程16进制值找到线程代码.

Sonar6.0应用之二:Sonar Web界面配置及与Runner、Scanner集成进行命令行代码分析

一.安装好了SonarQube服务端后,在其它电脑的浏览器上登陆,开始安装其它编程语言检测插件 系统已经装好的语言插件: 下载了软件项目中常用的语言:Android.CSS.Web.XML JAVA相关的:Checkstyle.Findbugs.PMD Java 静态分析工具分析对象 应用技术 Checkstyle Java 源文件,缺陷模式匹配 FindBugs 字节码,缺陷模式匹配:数据流分析 PMD Java 源代码,缺陷模式匹配 下载完分析语言规则后,重启服务 二.安装命令行分析端 so

CSP 命令行选项(201403-3)

问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项.每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔.这些字符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用对它进行处理.在工具名字之后可能会包含若干选项,然后可能会包含一 些不是选项的参数. 选项有两类:带参数的选项和不带参数的选项.一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如"-a" 或"-b".而带参数选项则由两个由空格分隔的字符串构成,前者的格式要求与无

CCF真题之命令行选项

201403-3 问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项.每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔.这些字符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用对它进行处理.在工具名字之后可能会包含若干选项,然后可能会包含一 些不是选项的参数. 选项有两类:带参数的选项和不带参数的选项.一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如"-a" 或"-b".而带参数选项则由两个由空格分隔的字符串构成,

首届CCF真题3-命令行选项

问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些选项.每个命令行由若干个字符串组成,它们之间恰好由一个空格分隔.这些字 符串中的第一个为该命令行工具的名字,由小写字母组成,你的程序不用 对它进行处理.在工具名字之后可能会包含若干选项,然后可能会包含一些不是选项的参数. 选项有两类:带参数的选项和不带参数的选项.一个合法的无参数选项的形式是一个减号后面跟单个小写字母,如"-a" 或"-b".而带参数 选项则由两个由空格分隔的字符串构成,前者的格式要求

python 命令行参数解析 argparse简单分析

在python 2.7 后,不推荐使用 optparse, 而推荐使用 argparse. 其它的不多说,简单的分析下我遇到的问题:我是想用 argparse 来解析不定长的命令行参数 例如: import argparse import sys parser = argparse.ArgumentParser(description='test parsing arguments') parser.add_argument('pos1', nargs='*') parser.add_argum

第5章4节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 命令行参数解析(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 设置好Monkey的CLASSPATH环境变量以指定"/system/framework /framework/monkey.jar"后,/system/bin/monkey这个shell脚本就会通

tcpdump教程 - 从命令行抓取和分析数据包

前言 在介绍和使用tcpdump之前,请确保您已经掌握或者了解如下几个关键概念,否则后面的内容让你有点痛苦. 能够在Linux命令行下工作 理解OSI七层网络协议的概念 熟悉各层的协议头部,重点是IP/TCP/UDP 交换机和路由器对应于OSI的协议层 另外还需要注意的是: tcpdump是基于Unix系统的命令行式的数据包嗅探工具.如果要使用tcpdump抓取其他主机MAC地址的数据包,必须开启网卡混杂模式,所谓混杂模式,用最简单的语言就是让网卡抓取任何经过它的数据包,不管这个数据包是不是发给

getopt函数(分析命令行参数)

相关函数表头文件 #include<unistd.h>定义函数 int getopt(int argc,char * const argv[ ],const char * optstring);函数说明 getopt()用来分析命令行参数.参数argc和argv是由main()传递的参数个数和内容.参数optstring 则代表欲处理的选项字符串.此函数会返回在argv 中下一个的选项字母,此字母会对应参数optstring 中的字母.如果选项字符串里的字母后接着冒号“:”,则表示还有相关的参