Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Python: Python3 - lainausmerkit merkkijonon sisällä

Sivun loppuun

juhohe [21.07.2009 13:19:19]

#

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?

Chiman [21.07.2009 13:24:35]

#

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.

Metabolix [21.07.2009 13:25:59]

#

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.

juhohe [21.07.2009 15:43:03]

#

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ä.

Metabolix [21.07.2009 16:43:39]

#

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: "

juhohe [30.07.2009 10:17:41]

#

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.

Chiman [30.07.2009 10:50:16]

#

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.

juhohe [30.07.2009 13:57:34]

#

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)".

Chiman [30.07.2009 14:07:20]

#

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ä

juhohe [30.07.2009 14:33:31]

#

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.

Chiman [30.07.2009 15:06:07]

#

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

juhohe [30.07.2009 15:55:17]

#

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ä.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta