findstr的命令行分析機(jī)制

2018-11-06 10:30 更新

來(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ò)


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)