來(lái)源:http://www.cn-dos.net/forum/viewthread.php?tid=21167&fpage=1&highlight=findstr
問題緣起于bsijl一篇關(guān)于findstr錯(cuò)誤過(guò)濾的主題[1],當(dāng)時(shí)因?yàn)闊o(wú)法找到原因,所以只能推測(cè) /g 開關(guān)存在某些問題。
近日,因?yàn)榫帉懸粋€(gè)debuger代碼,再次使用了 findstr/g ,結(jié)果遇到了同樣的問題[2]。經(jīng)過(guò)仔細(xì)的測(cè)試[3]后,發(fā)現(xiàn)是 findstr
特殊的命令行分析機(jī)制所引起的問題。略述如下:
1、findstr不同于早期的find,它對(duì)參數(shù)的排列有一定的要求,即遵循開關(guān)(可省略)、字符串(使用/c開關(guān)時(shí)省略)、文件名(可通配、可多個(gè)、有輸入流時(shí)需省略)的順序。
2、開關(guān)可以使用引號(hào),所以不能直接以與開關(guān)相同的關(guān)鍵字進(jìn)行搜索;文件名含空格時(shí)必須用引號(hào)。
3、搜索關(guān)鍵字的情況和表現(xiàn)就比較復(fù)雜,分述如下:
3-1、無(wú)論是否使用開關(guān)/l或/r以及是否使用引號(hào),關(guān)鍵字中的\都會(huì)成為轉(zhuǎn)義字符,所以\\將成為\,\"將使引號(hào)失去字符串界定作用;
3-2、搜索關(guān)鍵字可加或不加引號(hào),當(dāng)加引號(hào)時(shí)其中的\可能會(huì)再次轉(zhuǎn)義。使用開關(guān)/l和/r時(shí)的轉(zhuǎn)義結(jié)果可能會(huì)不同:當(dāng)使用/r時(shí),所以"\\\\"將成為單個(gè)\,"\\"將使關(guān)鍵字為空;當(dāng)使用/l或均不使用時(shí),"\\\\"和"\\"與單個(gè)\等價(jià)。
3-3、如果關(guān)鍵字以單個(gè)\結(jié)尾,且無(wú)引號(hào),則不會(huì)被轉(zhuǎn)義;
而 findstr/g出現(xiàn)的問題,應(yīng)該與上述內(nèi)容有關(guān),但其內(nèi)在機(jī)理仍無(wú)法透徹理解。不知各位有何高見?
[1]批處理刪除XP輸入法問題!請(qǐng)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
金牌會(huì)員
『第 2 樓』:
在我的XP上這個(gè)結(jié)果如何解釋?
d:\work>findstr /v /g:envar.out envar.out
FINDSTR: 搜索字符串太長(zhǎng)。
d:\work>findstr /v /g:envar.out envar.out
FINDSTR: 搜索字符串太長(zhǎng)。
d:\work>findstr /v /g:envar.out
FINDSTR: 搜索字符串太長(zhǎng)。
無(wú)奈何
版主
『第 3 樓』:
在我的 XP 下和 willsort 兄 3、的描述相同。這個(gè)惱人的結(jié)果不知道能不能確定是
FINDSTR 的 BUG ,請(qǐng)朋友們多試一下其它系統(tǒng)的情況??磥?lái)關(guān)鍵字中含有 “\”
字符應(yīng)該多加小心了。
3742668
版主
『第 4 樓』:
唔,似乎只有當(dāng)\后面的字符為非字母和非數(shù)字的時(shí)候才會(huì)出錯(cuò)。感覺microsoft準(zhǔn)備把findstr做成cmd下的正則表達(dá)式工具似的,但是又沒有考慮到與其他參數(shù)之間的兼容性,導(dǎo)致最后的結(jié)果是畫虎不成反類犬。
另外在某些時(shí)候,findstr的查找字符串中包含中文時(shí),需要加上/i參數(shù)才能避免錯(cuò)誤,具體環(huán)境以及代碼已忘,或許findstr除了正則表達(dá)式方面的bug外還存在unicode與ascii轉(zhuǎn)換的bug。
willsort
版主
『第 5 樓』:
Re Ups:
另外一個(gè)問題:
因?yàn)殚_關(guān)也允許引號(hào),所以無(wú)法以 "/l" 或 "/r"
等與開關(guān)相同的文本串作為關(guān)鍵字匹配,下面的句式將會(huì)出錯(cuò):
echo /l /r > test
findstr /l "/r" test
不過(guò),可以使用開關(guān) /c 來(lái)強(qiáng)制指定關(guān)鍵字:
findstr /l /c:"/r" test
findstr /l /c:/r test
還有一個(gè)方法,就是上文提到的 \ 了:
findstr /l \/r test
此外,這個(gè) \ 還可以讓我們的關(guān)鍵字中包含引號(hào):
echo /l /r >test
echo "/r" >> test
findstr /l \"/r\" test
最后,修訂和增補(bǔ)頂樓3-2中的一些描述:
3-2、開關(guān)/r和開關(guān)/l相同,其后的關(guān)鍵字均可使用或不使用引號(hào);使用引號(hào)時(shí):
3-2-1、"\"和"\\\"等價(jià)于引號(hào)和其后各個(gè)串所各自代表的多個(gè)關(guān)鍵字;
3-2-2、"\\\\\"和"\\\\\\\"等價(jià)于引號(hào)加\組成的關(guān)鍵字和其他多個(gè)關(guān)鍵字;
3-2-3、"\\\\\\\\\"等價(jià)于引號(hào)加\\組成的關(guān)鍵字和其他多個(gè)關(guān)鍵字;
3-2-4、"\ ","\\","\\\ ","\\\\\
","\\\\\\","\\\\\\\ "等價(jià)于空;
3-2-5、"\\ ","\\\\"等價(jià)于一個(gè)\;
3-2-6、"\\\\ ","\\\\\\\\"等價(jià)于兩個(gè)\;
3-2-7、"\\\\\\ "等價(jià)于三個(gè)\;
3-2-8、"\\\\\\\\ "等價(jià)于四個(gè)\;
以上數(shù)據(jù)由以下方法測(cè)得,測(cè)試文件見[1][2],當(dāng)不使用/r開關(guān)與使用開關(guān)/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、開關(guān)/r和開關(guān)/l相同,其后的關(guān)鍵字均可使用或不使用引號(hào);使用引號(hào)時(shí):
3-2-1、"\"和"\\\"等價(jià)于引號(hào)和其后各個(gè)串所各自代表的多個(gè)關(guān)鍵字;
3-2-2、"\\\\\"和"\\\\\\\"等價(jià)于引號(hào)加\組成的關(guān)鍵字和其他多個(gè)關(guān)鍵字;
3-2-3、"\\\\\\\\\"等價(jià)于引號(hào)加\\組成的關(guān)鍵字和其他多個(gè)關(guān)鍵字;
3-2-4、"\ ","\\","\\\ ","\\\\\
","\\\\\\","\\\\\\\ "等價(jià)于空;
3-2-5、"\\ ","\\\\"等價(jià)于一個(gè)\;
3-2-6、"\\\\ ","\\\\\\\\"等價(jià)于兩個(gè)\;
3-2-7、"\\\\\\ "等價(jià)于三個(gè)\;
3-2-8、"\\\\\\\\ "等價(jià)于四個(gè)\;
我早前也發(fā)現(xiàn)這規(guī)律存在路徑名上,只是沒深入研究,沒敢貼上來(lái).
我是從"dir .\", " dir ..\" 開始,大家不妨測(cè)試下.
willsort
版主
狀態(tài) 離線 『第 7 樓』:
Re 220110:
UNC 路徑名中 \ 的解析與 findstr
關(guān)鍵字是不同的,它只有界定目錄的作用,而沒有轉(zhuǎn)義字符的作用。
另外,findstr /v ^%var%$ test.txt 語(yǔ)句中,如果test.txt最后一行就是要匹配的%var%,且該行不為空,則不能過(guò)濾最后一行的內(nèi)容,似乎是分行標(biāo)志識(shí)別出了錯(cuò)
更多建議: