Avatar billede sumokadet Nybegynder
04. august 2008 - 09:56 Der er 16 kommentarer og
2 løsninger

Find filer indeholdende bestemt streng (Python/Script/e.lign.)

Jeg sidder med følgende problemstilling, som jeg håber at I kan hjælpe mig med.

"Find alle filer (af typen .py/.xml) i en mappe og alle undermapper herunder som opfylder følgende: Der skal være mindst en streng (indkapslet i "" eller ''), som ikke har en funktion MSGR("") rundt om sig. Returner navnet på de filer der opfylder kriterier samt linjenumre heri hvor at der er fundet noget."

Et par eksempler giver det nok bedre:

Skal findes:
* "Hello world"
* 'Hello world'
* MSGR('Hello world')

Skal ikke findes
* MSGR("Hello world")

Den bagvedliggende forklaring er at jeg ønsker at få alle strenge i mine filer indkapslet i en MSGR()-funktion for oversættelses øjemed.

Til min rådighed har jeg det meste af hvad der kan flyve på et linux-system, men det skal helst kunne laves i et standard Shell-script eller Python-program. Jeg kunne forestille mig at det var en let ting at lave ved brug af et regexp i midten. Det behøver ikke være noget fancy - jeg skal sådan set bare bruge noget der virker, og så lære lidt heraf.

Hvis jeg ikke har forklaret problemstillingen godt nok må i endelig skrive tilbage med spørgsmål og jeg skal forsøge at klargøre.
Avatar billede bauerdata Nybegynder
04. august 2008 - 12:04 #1
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
"""
filename findStrgs.py
"""
import findfiler
import grep
Query = """
    Jeg sidder med følgende problemstilling, som jeg håber at I kan hjælpe mig med.
   
    "Find alle filer (af typen .py/.xml) i en mappe og alle undermapper herunder som
    opfylder følgende: Der skal være mindst en streng (indkapslet i "" eller ''), som
    ikke har en funktion MSGR("") rundt om sig. Returner navnet på de filer der opfylder
    kriterier samt linjenumre heri hvor at der er fundet noget."
   
    Et par eksempler giver det nok bedre:
   
    Skal findes:
    * "Hello world"
    * 'Hello world'
    * MSGR('Hello world')
   
    Skal ikke findes
    * MSGR("Hello world")
   
    Den bagvedliggende forklaring er at jeg ønsker at få alle strenge i mine filer
    indkapslet i en MSGR()-funktion for oversættelses øjemed.
   
    Til min rådighed har jeg det meste af hvad der kan flyve på et linux-system, men det
    skal helst kunne laves i et standard Shell-script eller Python-program. Jeg kunne
    forestille mig at det var en let ting at lave ved brug af et regexp i midten. Det
    behøver ikke være noget fancy - jeg skal sådan set bare bruge noget der virker, og
    så lære lidt heraf.
   
    Hvis jeg ikke har forklaret problemstillingen godt nok må i endelig skrive tilbage
    med spørgsmål og jeg skal forsøge at klargøre.
"""

OSuff = set( ['xml', 'py'] )
IDirs = set([ 'cis_to_araxml', '.svn', "Zope-2.10.4-final" ])

SearchString = """'Hello world'|[^(]"Hello world"|MSGR('Hello world')"""

foundFiles = findfiler.find(Path=".", onlySuffix=OSuff, IgnoreDirs=IDirs)

retVal = {}
for fname in foundFiles:
    val =  grep.grep_lines(fname, SearchString )
    if val:
        retVal[ fname ] = val
print retVal.items()
Avatar billede bauerdata Nybegynder
04. august 2008 - 12:05 #2
#!/usr/bin/env python
#
""" filename grep.py
import os
import re
compiledRegs = {}

def grep_lines(filename, regex):
    global compiledRegs
    try:
        f=open(filename)
    except IOError, e:
        print e
        return False
    Flag=0
    try:
        reg = compiledRegs[regex]
    except:
        reg = re.compile(regex,Flag)
        compiledRegs[regex] = reg

    retval = []
    line = f.readline()
    lineNo = 1
    while line:
        if reg.findall(line):
            retval.append( lineNo )
        line = f.readline()
        lineNo += 1
    return retval


def grep(filename, regex, flags=""):
    """Search filename for regex"""
    global compiledRegs
    try:
        f=open(filename)
    except IOError, e:
        print e
        return False
    Flag=0
    if "i" in flags:
        Flag=re.I
    try:
        reg = compiledRegs[regex]
    except:
        reg = re.compile(regex,Flag)
        compiledRegs[regex] = reg

    line = f.readline()
    while line:
        if reg.findall(line):
            f.close()
            return True
        line = f.readline()
    f.close()
    return False

if __name__ == "__main__":
    print grep("filename.txt","bauer")
    print grep("filename.txt","hej")
Avatar billede bauerdata Nybegynder
04. august 2008 - 12:06 #3
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""Usage: python findfiler [-v] [<path>] [-s <suffix> ] [-S <IgnoresSuffix>] [-D <IgnoreDir>]
    <path>: default to "." angiver søgnings startpunkt
    <IgnoresSuffix>: Sufix to ignore defalt to []
    <IgnoreDir>: dirs to ignore defalt to []
    Returns a list off filenames
"""
import sys
import os
from os.path import isfile

def find(Path=".", onlySuffix=set(), IgnoreSuffix=set(), IgnoreDirs=set(), vim="" ):
    """find [<path>] [<IgnoresSuffix>] [<IgnoreDir>]
        <path>: default to "." angiver søgnings startpunkt
        <onlySuffix>    : only this suffix
        <IgnoresSuffix> : Sufix to ignore defalt to []
        <IgnoreDir>    : dirs to ignore defalt to []
        <vim>          : drop files ending with this string
        Returns a list off filenames ignoring pipes.
    """
    Foundnames = []
    for dirpath, dirnames, filenames in os.walk( Path ) :
        Idirs = set(tuple(Dir for Dir in dirpath.split("/")))
        if Idirs.intersection( IgnoreDirs):
            continue
        for fname in filenames :
            if not isfile(fname):
                continue
            suffix=fname.split(".")[-1]
            if vim and fname.endswith(vim): continue
            if onlySuffix:
                if suffix not in onlySuffix:
                    continue
            elif suffix in IgnoreSuffix:
                continue
            Foundnames.append( "%(dirpath)s/%(fname)s" % vars() )
    return Foundnames


if __name__ == "__main__":
    try:
        Path = sys.argv[ 1 ]
    except:
        Path = "."
    if Path == "-h":
        print "Usage", __doc__
        sys.exit(0)
    ISuff = set(("pcikler", "swp", "swm", "html", "xml", "csv", "pyc", "py~"))
    IDirs = set(("static", "pngs", "frozen", "cis_to_araxml", "cis_to_xml", "Zope-2.10.4-final"))
    OSuff = set(("py", "txt", "xml", "html", "csv" ))
    print find(Path=Path, onlySuffix=OSuff, IgnoreSuffix=ISuff, IgnoreDirs=IDirs)
    print "finished"
Avatar billede bauerdata Nybegynder
04. august 2008 - 12:08 #4
installer de tre ovenstående python programmer.
og kør findStrgs.py
Avatar billede bauerdata Nybegynder
04. august 2008 - 12:09 #5
regex kan godt forbedres , men virker sikker helt godt i praksis :-)
Avatar billede bauerdata Nybegynder
04. august 2008 - 12:10 #6
grep.py mangler """ sidst på linie 3
Avatar billede sumokadet Nybegynder
04. august 2008 - 13:54 #7
Ser rigtigt godt ud. Sidder lige og prøver at få det op at flyve. Får følgende syntaks fejl, da jeg ikke umiddelbart er skarp i Python, kan du så se den?

Traceback (most recent call last):
  File "findStrgs.py", line 7, in ?
    import findfiler
  File "/users/alexa/work/Customization/dsb_user/findfiler.py", line 24
    Idirs = set(tuple(Dir for Dir in dirpath.split("/")))
                            ^

Desuden ønsker jeg at kunne finde arbitrære strenge og ikke bare Hello world'er. Men så vidt jeg kan gennemskue kunne dette hurtigt ændres i SearchString = """'Hello world'|[^(]"Hello world"|MSGR('Hello world')""" hvor jeg måske bare kunne erstatte Hello world med en * (stjerne) e.lign.?
Avatar billede sumokadet Nybegynder
04. august 2008 - 13:59 #8
Jeg får desuden også

Traceback (most recent call last):
  File "findStrgs.py", line 7, in ?
    import findfiler
  File "/users/alexa/work/Customization/dsb_user/findfiler.py", line 13, in ?
    def find(Path=".", onlySuffix=set(), IgnoreSuffix=set(), IgnoreDirs=set(), vim="" ):
NameError: name 'set' is not defined
Avatar billede bauerdata Nybegynder
04. august 2008 - 14:26 #9
det ser ud til at du ikke bruger python 2.5 så set er ikke kendt

Ja det er SearchString som du skal bruge til at ændre søgninger :-)
Avatar billede sumokadet Nybegynder
04. august 2008 - 14:47 #10
Kan du gennemskue hvordan jeg kan ændre din løsning, da jeg bruger v. 2.3.4 og bestemt ikke har nogle rettigheder til at kunne opgradere denne...?

Tusind tak for hjælpen...
Avatar billede bauerdata Nybegynder
04. august 2008 - 18:33 #11
du ændrer alle set([...]) til [...]
og i findfiler.py
ændrer du
linierne
        Idirs = set(tuple(Dir for Dir in dirpath.split("/")))
        if Idirs.intersection( IgnoreDirs):
            continue

til
        Idirs = [ Dir for Dir in dirpath.split("/") if Dir in IgnoreDirs ]
        if Idirs:
            continue
Avatar billede sumokadet Nybegynder
05. august 2008 - 12:04 #12
Tak for din hjælp. Ændrede det efter dine forslag og nu kører det. Desværre er der et par få problemer tilbage. Du giver pokkers god hjælp, så hvis du lige hjælper mig i mål, kan vi nok godt finde ud af noget med lidt flere point.

Jeg lavede en testfil, som burde kunne findes, indeholdende følgende linje:

  Denne fil "boer" kunne findes.

Den blev også fundet hvis den lå i samme udgangsmappe som dit program men ikke hvis den lå i undermapper. Så lavede jeg en anden testfil, som ikke burde findes da den ikke opfylder kriterier:

  Denne fil boer ikke kunne findes.

Denne fil blev desværre også fundet, så det virker som om at det regulære udtryk ikke virker helt efter planen. Jeg benytter SearchString = """'.+'|[^(]".+"|MSGR('.+')""", men det lader ikke helt til at virke. Kriteriet var som bekendt at finde alle strenge der enten var "xxx" eller "yyy" eller MSGR('zzz') (arbitrær længde > 0) men ikke MSGR("www").
Avatar billede bauerdata Nybegynder
05. august 2008 - 12:25 #13
regex er ikke min stærke side
men det her kunne måske hjælpe
["""'\w'|"\w"[^)]|MSGR\(\w\)"""


\w
    Matches any alphanumeric character; this is equivalent to the class

se i øvrigt http://docs.python.org/dev/howto/regex.html
Avatar billede sumokadet Nybegynder
05. august 2008 - 12:26 #14
Hej, se bort fra ovenstående kommentarer. Må erkende at jeg har sovet i timen og kørt den forkerte fil. Så der blev aldrig kørt reg-udtryk på filen.

Den søger dog stadig ikke ned i underbiblioteker, men jeg vil kigge lidt videre på det, burde være til at hitte ud af. Vil ikke have at du laver unødigt arbejde ift. min dumhed med regulære udtryk-fejlen :-)
Avatar billede bauerdata Nybegynder
05. august 2008 - 12:27 #15
ups """'\w+'|"\w+"[^)]|MSGR\(\w+\)"""
Avatar billede sumokadet Nybegynder
05. august 2008 - 12:53 #16
Har fundet fejlen. Den lå i find-funktionen. Følgende

if not isfile(fname):
  continue

Gav altid continue når at filen ikke lå i samme sti som udgangspunkt. Kunne nok rettes med at concatinere stien på istedet for fname, så dirpath + fname agtigt noget. Jeg udkommenterede de to linjer og det fungerede også fint.

Tak for din hjælp.
Avatar billede sumokadet Nybegynder
05. august 2008 - 13:33 #17
bauerdata, se http://www.eksperten.dk/spm/840524 for lidt flere point
Avatar billede bauerdata Nybegynder
05. august 2008 - 13:39 #18
Så fik vi jo hjulpet begge veje :-)
if isfile( "%s/%s" % (dirpath, fname ) ):
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester