glob(3f) - [M_unicode:COMPARE] compare given string for match to a pattern which may contain globbing wildcard characters (LICENSE:MIT)
Synopsis
Description
Options
Examples
Author
References
License
logical function glob(string, pattern ) result (uline)
type(unicode_type),intent(in) :: string ! or character(len=*),intent(in) :: stringtype(unicode_type),intent(in) :: pattern ! or character(len=*),intent(in) :: pattern
logical :: uline
glob(3f) compares an (entire) STRING for a match to a PATTERN which may contain basic wildcard "globbing" characters.In this version to get a match the entire string must be described by PATTERN. Trailing whitespace is significant, so trim the input string if it is desired to ignore trailing whitespace.
o "*" matches any string. o "?" matches any single character. o a NULL may not appear in the input strings o trailing whitespace is significant A NULL character is added to the input strings internally to avoid early matches. Without this, patterns like "b*ba" fail on a string like "babababa" because the first match found is not at the end of the string so baba does not match babababa. So the algorithm is said to find an early match.
One method that allows skipping over the early matches is to insert an extra character at the end of the string and pattern that does not occur in the pattern. Typically a NULL is used (char(0)), as it is here. So searching for b*ba\0 in babababa\0 matches the entire string.
string the input string to be tested for a match to the pattern. pattern the globbing pattern to search for. The following simple globbing rules apply:
o "?" matching any one character o "*" matching zero or more characters. Do NOT use adjacent asterisks. o The input strings must not contain a NULL character o spaces are significant and must be matched. o There is no escape character, so matching strings with a literal question mark and asterisk is problematic.
Example program
program demo_glob use M_unicode, only : glob, trim, unicode_type, len use M_unicode, only : escape use M_unicode, only : assignment(=) implicit none integer :: i type(unicode_type),allocatable :: ufiles(:) type(unicode_type),allocatable :: matched(:) character(len=*),parameter :: & filenames(*)= [character(len=256) :: & & My_favorite_file.F90, & ! English & 我最喜欢的文档.c, & ! Mandarin_Chinese & मेरी_पसंदीदा_फ़ाइल.f90, & ! Hindu & Mi_archivo_favorito.c, & ! Spanish & ملفي_المفضل.h, & ! Modern_Standard_Arabic & Mon_fichier_préféré.f90, & ! French & আমার_প্রিয়_ফাইল, & ! Bengali & Meu_arquivo_favorito, & ! Portuguese & Мой_любимый_файл, & ! Russian & میری_پسندیدہ_فائل.pdf, & ! Urdu & src/M_modules.F90, & & src/subset.inc, & & test/check.f90 , & & app/main.f90 ] character(len=*),parameter :: & encoded(*)= [character(len=256) :: & & My_favorite_file.F90, & ! English & \u6211\u6700\u559C\u6B22\u7684\u6587\u6863.c, & ! Mandarin_Chinese & \u092E\u0947\u0930\u0940_& &\u092A\u0938\u0902\u0926\u0940\u0926\u093E_& &\u092B\u093C\u093E\u0907\u0932.f90, & ! Hindu & Mi_archivo_favorito.c, & ! Spanish & \u0645\u0644\u0641\u064A_& &\u0627\u0644\u0645\u0641\u0636\u0644.h , & ! Modern_Standard_Arabic & Mon_fichier_pr\xE9f\xE9r\xE9.f90, & ! French & \u0986\u09AE\u09BE\u09B0_\u09AA\u09CD\u09B0\u09BF\u09AF\u09BC_& &\u09AB\u09BE\u0987\u09B2, & ! Bengali & Meu_arquivo_favorito, & ! Portuguese & \u041C\u043E\u0439_\u043B\u044E\u0431\u0438\u043C\u044B\u0439_& &\u0444\u0430\u0439\u043B, & ! Russian & \u0645\u06CC\u0631\u06CC_& &\u067E\u0633\u0646\u062F\u06CC\u062F\u06C1_& &\u0641\u0627\u0626\u0644.pdf, & ! Urdu & src/M_modules.F90, & & src/subset.inc, & & test/check.f90 , & & app/main.f90 ] character(len=*),parameter :: & g=(*(g0)), g1=(*(g0,1x)), comma=(*(g0:,", ",/))Results:! some basic usage write(*,g)merge(PASSED,FAILED,glob("mississipPI", "*issip*PI")) write(*,g)merge(PASSED,FAILED,glob("bLah", "bL?h")) write(*,g)merge(PASSED,FAILED,glob("bLaH", "?LaH"))
! create a list of trimmed filenames ufiles=unicode_type(filenames) ufiles=trim(ufiles) write(*,g)FILENAMES: call show_filenames(ufiles)
! create a list of trimmed filenames from encoded names ufiles=escape(encoded) ufiles=trim(ufiles) write(*,g)ENCODED FILENAMES: call show_filenames(ufiles)
! get filenames ending in ".f90" matched=pack(ufiles,glob(ufiles,*.f90)) write(*,g)MATCHED *.f90: call show_filenames(matched)
! get filenames ending in ".c" matched=pack(ufiles,glob(ufiles,*.c)) write(*,g)MATCHED *.c: call show_filenames(matched)
contains subroutine show_filenames(names) type(unicode_type),allocatable :: names(:) write(*,g1):SIZE:,size(names),:LEN:,len(names) write(*,comma)(names(i)%character(),i=1,size(names)) end subroutine show_filenames
end program demo_glob
> PASSED > PASSED > PASSED > FILENAMES: > :SIZE: 14 :LEN: 20 9 22 21 13 23 16 20 16 21 17 14 14 12 > My_favorite_file.F90, > 我最喜欢的文档.c, > मेरी_पसंदीदा_फ़ाइल.f90, > Mi_archivo_favorito.c, > ملفي_المفضل.h, > Mon_fichier_préféré.f90, > আমার_প্রিয়_ফাইল, > Meu_arquivo_favorito, > Мой_любимый_файл, > میری_پسندیدہ_فائل.pdf, > src/M_modules.F90, > src/subset.inc, > test/check.f90, > app/main.f90 > ENCODED FILENAMES: > :SIZE: 14 :LEN: 20 9 22 21 13 23 16 20 16 21 17 14 14 12 > My_favorite_file.F90, > 我最喜欢的文档.c, > मेरी_पसंदीदा_फ़ाइल.f90, > Mi_archivo_favorito.c, > ملفي_المفضل.h, > Mon_fichier_préféré.f90, > আমার_প্রিয়_ফাইল, > Meu_arquivo_favorito, > Мой_любимый_файл, > میری_پسندیدہ_فائل.pdf, > src/M_modules.F90, > src/subset.inc, > test/check.f90, > app/main.f90 > MATCHED *.f90: > :SIZE: 4 :LEN: 22 23 14 12 > मेरी_पसंदीदा_फ़ाइल.f90, > Mon_fichier_préféré.f90, > test/check.f90, > app/main.f90 > MATCHED *.c: > :SIZE: 2 :LEN: 9 21 > 我最喜欢的文档.c, > Mi_archivo_favorito.c
John S. Urban
The article "Matching Wildcards: An Empirical Way to Tame an Algorithm" in Dr Dobbs Journal, By Kirk J. Krauss, October 07, 2014
