;+ ;FUNCTION: ; res = strfilter(stringarray,searchstring) ;PURPOSE: ; Returns the subset of stringarray that matchs searchstring ; '*' will match all (non-null) strings ; '' will match only the null string ; Output can be modified with keywords ; NOTE: this routine is very similar to the STRMATCH routine introduced in IDL 5.3 ; it has some enhancements that make it useful. ; (i.e.: filterstring can also be an array) ;INPUT: ; stringarray: An array of strings to be filtered ; searchstring: A string that may contain wildcard characters ("*") ; (If searchstring is an array then results are OR'd together) ;RETURN VALUE: ; Either: ; Array of matching strings. ; or: ; Array of string indices. ; or: ; Byte array with same dimension as input string. ; Depends upon keyword setting (See below) ; ;KEYWORDS: ; FOLD_CASE: if set then CASE is ignored. (only IDL 5.3 and later) ; STRING: if set then the matching strings are returned. (default) ; INDEX: if set then the indices are returned. ; BYTES: if set then a byte array is returned with same dimension as input string array (similar to STRMATCH). ; NEGATE: pass only strings that do NOT match. ; COUNT: A named variable that will contain the number of matched strings. ; NO_MATCH: A named variable that will contain either a subset of searchstring that ; failed to match stringarray, an array of indices to that subset, or a ; byte array whose dimensions match the number of elements in searchstring. ; The data type returned will match that of the return value. ; (only IDL 5.3 and later) ;Limitations: ; This function still needs modification to accept the '?' character ; July 2000; modified to use the IDL strmatch function so that '?' is accepted for versions > 5.4 ;EXAMPLE: ; Print,strfilter(findfile('*'),'*.pro',/negate) ; print all files that do NOT end in .pro ;AUTHOR: ; Davin Larson, Space Sciences Lab, Berkeley; Feb, 1999 ;VERSION: 01/10/08 ;- function strfilter,str,matchs,count=count, $ wildcard=wildcard,fold_case=fold_case, $ delimiter=delimiter, no_match=no_match, $ index=index,string=retstr,byte=bt,negate=negate if !version.release ge '5.3' then begin matcharray = keyword_set(matchs) ? matchs : '' if keyword_set(delimiter) and size(/dimen,matcharray) eq 0 then $ matcharray = strsplit(matcharray,delimiter,/extract) if keyword_set(wildcard) then dprint,'Wildcard "'+wildcard+'" ignored' ;initialize vars for return values and substrings with no matches ret = 0b missed = replicate(1b, n_elements(matcharray)) ;loop over substrings to find matches within the array for k=0,n_elements(matcharray)-1 do begin new = strmatch(str,matcharray[k],fold_case=fold_case) ret = new or ret if total(new) gt 0 then missed[k] = 0b endfor ;pass back info on which searches found no matches, ;the type of data passed back should match that of the return value midx = where(missed, nm) no_match = nm gt 0 ? matcharray[midx] : '' if keyword_set(string) then no_match = no_match if keyword_set(index) then no_match = midx if keyword_set(bt) then no_match = missed endif else begin ; Old version follows: ns = strlen(str) ret = ns eq -1 ; set to 0 if not keyword_set(wildcard) then wildcard='*' for k=0,n_elements(matchs)-1 do begin match = matchs[k] ;mss=str_sep(match,wildcard) mss=strsplit(match,wildcard,/extract) nmss= keyword_set(match) ? n_elements(mss) : 0 ;quick test to improve speed, required to find a null string if match eq wildcard then begin ret[*] = 1 goto,skip ; pass all strings endif ;quick test to improve speed, but not required if nmss eq 1 then begin ;no wildcards to match do the simple thing ret = (str eq match) or ret goto,skip endif lms = strlen(mss) for i=0,n_elements(str)-1 do begin ; Unfortunately strmid and strpos don't allow pos to be vectors temp = str[i] ; so an extra loop is required here p = 0 for j=0,nmss-1 do begin p2 = (j lt nmss-1) ? strpos(temp,mss[j],p) : rstrpos(temp,mss[j]) if j eq 0 then r = (p2 eq 0) else r = (p2 ge p) p = p2 + lms[j] if r eq 0 then goto,break endfor r = p eq ns[i] break: ret[i]= ret[i] or r endfor skip: endfor endelse ; end of old version if keyword_set(negate) then ret = (ret eq 0) ind = where(ret,count) nstr = count eq 0 ? '' : str[ind] if keyword_set(retstr) then return, nstr if keyword_set(index) then return, ind if keyword_set(bt) then return, ret ;message,/info,'Please use KEYWORD, default will change to STRING' return,nstr ; this default may change! end