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