Teen sananhakuohjelmaa, joka toimii komentoriviltä käsin. Haluaisin tehdä niin, että haettava sana pitää kirjoittaa lainausmerkkien sisään, niin että ohjelma toimisi tapaan:
python3 ohjelma.py "sana"
Tällä tavalla olen yrittänyt sitä toteuttaa, mutta en saa toimimaan.
import sys, re x = re.search(r'(?<=\")\w+(?=\")', sys.argv[1]) print(x)
Tulostukseksi tulee None. Miten Pythonin saisi tajuamaan, että haluan säilyttää komentorivillä asettamani lainausmerkit?
Kokeile
print(sys.argv)
Näkyykö lainausmerkkejä? Jos ei, ne eivät välity pythonille komentoriviltä. Mahdollinen keino:
python3 ohjelma.py \"sana\"
Edit: Olennainen kysymys on tietysti se, miksi haluat asettaa ne lainausmerkkeihin. Esim. käyttämällä pythonin optparse-moduulia saat tehtyä monipuolisen ja kätevän komentorivisyötteiden hallinnan.
Kysehän ei ole Pythonin ominaisuudesta vaan siitä, että komentorivi tulkitsee lainausmerkkeihin kirjoitetut asiat yhdeksi parametriksi. Seuraavassa on muutama ajokomento ja vastaavat parametrit ohjelmasta tulostettuina.
python ohjelma.py abcd -> 1: abcd python ohjelma.py ab cd -> 1: ab -> 2: cd python ohjelma.py "ab cd" -> 1: ab cd python ohjelma.py "ab cd" ef -> 1: ab cd -> 2: ef python ohjelma.py "ab"c"d"efg" "hij -> 1: abcdefg hij
Oikea ratkaisu on esimerkiksi tuo Chimanin ehdottama — tai voit lisätä lainausmerkit vasta ohjelmassa, jos tiedät muutenkin, että kyseinen parametri on kaivattu hakusana.
Kiitos neuvoista. Hyvä tietää, että se johtuu itse komentorivin toiminnasta, että lainausmerkit katoavat. Enpä oikeastaan tarvitsekaan niitä lainausmerkkejä, mutta olisi ollut kiva laittaa ne, koska ohjelmaani syötetään useita eri asetuksia komentorivillä, mutta saan ne kyllä erotettua toisistaan ilman lainausmerkkejäkin.
grep-ohjelmassa, joka toimii komentoriviltä, on minun tietääkseni pakko käyttää Linuxilla '-lainausmerkkejä hakusanan ympärillä ja Windowsin komentorivillä "-lainausmerkkejä.
juhohe kirjoitti:
grep-ohjelmassa, joka toimii komentoriviltä, on minun tietääkseni pakko käyttää Linuxilla '-lainausmerkkejä hakusanan ympärillä ja Windowsin komentorivillä "-lainausmerkkejä.
Ei, tämä ei pidä mitenkään paikkaansa. Linuxin komentotulkit vain tekevät monenlaisia korvauksia; ne tukevat muuttujia ja tietynlaisia muita lausekkeita. Perinteisesti osa korvauksista jätetään tekemättä, jos teksti on kirjoitettu '-merkkeihin. Linuxilla esimerkiksi näin:
MUUTTUJA=10 python ohjelma.py $MUUTTUJA > 1: 10 python ohjelma.py \$MUUTTUJA > 1: $MUUTTUJA python ohjelma.py "$MUUTTUJA" > 1: 10 python ohjelma.py "\$MUUTTUJA" > 1: $MUUTTUJA python ohjelma.py '$MUUTTUJA' > 1: $MUUTTUJA python ohjelma.py '\$MUUTTUJA' > 1: \$MUUTTUJA
Lainausmerkitkin saa välitettyä vastaavasti:
python ohjelma.py \" "\"" '"' > 1: " > 2: " > 3: "
Minulla on nyt komentorivipohjainen sanahakuohjelma, mutta haluaisin, jos mahdollista, toteuttaa asetusten syöttämisen optparsen avulla. Ennen tätä olen käyttänyt vain sys.argv-listaa, jonka alkioista olen säännöllisten lausekkeiden avulla. Minulla olisi tällainen alku:
from optparse import OptionParser usage = "usage: %prog [options] keyword file" parser = OptionParser(usage = usage) parser.add_option("-c", "--character", dest = "charcontext", help = """display the keyword in context of x,y characters. Number x characters on the left and number y characters on the right side.""") parser.add_option("-w", "--word", dest = "wordcontext", help = """works in the same way as -c except that words are used as the context objects instead of characters.""") parser.add_option("-l", "--line", dest = "linecontext", help = """same as -c and -w but with the keyword shown in line context.""") parser.add_option("-a", "--alignment", dest = "alignment", help = """Give negative or positive number to select which word you want to center before or after the keyword when the search results are printed out.""") (options, args) = parser.parse_args() if len(args) != 2: parser.error("incorrect number of arguments")
En ole varma, tuleeko se kyllin selväksi, mutta käyttäjän olisi tarkoitus ajaa ohjelma näin: ohjelma.py -w5,2 -a-1 hakusana tiedosto.txt. Ongelmia tulee, jos käyttäjä syöttää kaikki kolme -c, -w ja -l -optiot. Oletusasetukseksi haluaisin asettaa -l0,0.
Jos se olisi mahdollista, tahtoisin tehdä niin, nuo -c, -w ja -l olisivat ikään kuin vaihtoehtoina, ja numerot niiden jälkeen olisivat vapaaehtoiset. Jos numerot jätettäisiin syöttämättä, käytettäisiin oletusarvoja.
optparsen dokumentaatiossa sanotaan, että optio joko saa aina argumentin tai se ei saa sitä koskaan. Optioille ei voi olla vapaaehtoisia argumentteja, koska se tuottaisi tulkintaongelmia ("because it makes parsing ambiguous: if "-a" takes an optional argument and "-b" is another option entirely, how do we interpret "-ab"?").
Yksi keino on käyttää yhtä optiota toiminnon kytkemiseen ja toista (argumentillista) antamaan samalle toiminnolle oletuksesta poikkeava arvo.
Vielä kiinnostaisi, että onnistuisiko sellainen, että optio itse tallentuisi destiin? Niinkuin tapaan:
parser.add_option("-c", "--character", dest = "context", help = "display the keyword in context of x y characters.") parser.add_option("-w", "--character", dest = "context", help = "display the keyword in context of x y words.") parser.add_option("-l", "--character", dest = "context", help = "display the keyword in context of x y characters.")
Tarkoitan, että "context" saa arvoksi vaikka "(w, 1, 2)".
Muistaakseni tekemällä callbackin, mutta nyt kuulostaa siltä että olet etsimässä ratkaisua liian vaikeasti. Laitatko esimerkkejä komentoriveistä ja miten haluaisit niiden vaikuttavan ohjelmaan? Saako ryhmän c, l, w optioita olla kerralla käytössä vain yksi? Jos useita, miten niiden pitäisi vaikuttaa?
Testaaminen onnistuu helpoiten lisäämällä aiempaan koodiisi:
(options, args) = parser.parse_args() print 'options:', options print 'args:', args
Esim:
$ python options_test.py -a -1 -w5,2 b c options: {'wordcontext': '5,2', 'linecontext': None, 'alignment': '-1', 'charcontext': None} args: ['b', 'c']
Muoks: lisäselvennystä
Vain yksi optio näistä kolmesta eli -c, -w tai -l saa olla kerrallaan käytössä.
options.py -c15,2 hakusana teksti.txt
Tuollaisella hakisin ohjelmani avulla tekstitiedostosta sanaa "hakusana" niin, että ohjelma lopulta tulostaa tekstin kohdat sillä tavalla, että näytetään 15 merkkiä ennen hakusanaa, itse hakusana, ja 2 merkkiä vielä sen jälkeen.
options.py -l0,1 hakusana teksti.txt
Tämä taas hakisi hakusanaa ja tulostaisi sen esiintymät niin, että näytetään 0 riviä ennen hakusanaa, hakusanan sisältävä rivi ja sitä seuraava rivi. Tämän takia haluaisin sisällyttää numerot ja kirjainoptiot samaan muuttujaan. Olen miettinyt, että voisin kuitenkin tehdä vielä yhden option lisää, joka ei sisältäisi muuta kuin numerot. Kirjaimet olisivat erikseen toisessa muuttujassa. Tämän haittapuoli olisi vain se, että komentorivikomento tulee pidemmäksi.
Olen siis tehnyt muuten ohjelman jotakuinkin valmiiksi, mutta haluaisin tehdä nämä optiot optparsen avulla, jotta koodista tulisi siistimpi.
No nyt selvisi. Näin voit tarkistaa että saat vain yhden:
# only one allowed exclusive = (options.charcontext, options.wordcontext, options.linecontext) if len([x for x in exclusive if x]) > 1: parser.error("options -c, -w and -l are mutually exclusive")
Toinen vaihtoehto olisi ollut käyttää toista optiota valitsemaan yksi char/word/line-joukosta ja toista antamaan (oletuksesta poikkeava) arvo sille.
Esim.
options.py -Tc -n15,2 hakusana teksti.txt options.py -Tl -n0,1 hakusana teksti.txt options.py -Tw hakusana teksti.txt
Kiitos neuvoista!
Sopiiko muuten Ohjelmointiputkaan lähettää vaikka oman ohjelman koko lähdekoodi? Nimittäin meillä on ollut nyt Python-kurssi, jonka lopputyötä haluaisin vielä parannella oliopohjaiseen suuntaan. Sillä on pituutta joku 300 riviä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.