This tutorial describes how to deal with information passed in on the command line. Not the switches passed to the Perl interpreter, but the switches and ...
goahead...beaheretic
PerlMonks
Parsingyourscript'scommandline
bygrinder(Bishop)
Log inCreate a new user
The Monastery Gates
Seekers of Perl Wisdom
Meditations
Cool Uses For Perl
Obfuscation
Tutorials
Poetry
Reviews
Perl News
Donate
Recent Threads
Newest Nodes
Super Search
PerlMonks Discussion
What's New
onJun14,2001at02:04 UTC
(#88222=perltutorial:printw/replies,xml)
NeedHelp??
Thistutorialdescribeshowtodealwithinformationpassedinon
thecommandline.NottheswitchespassedtothePerlinterpreter,
buttheswitchesandfilenamesthatarepassedtoyourscript.
Thefirststeps
Let'sassumethatyouhavewrittenyourfirsthelloworldscript,
whichlookssomethinglikethis:
#!/usr/local/bin/perl-w
print"Hello,world\n";
[download]
Insteadofgreetingtheworld,youwouldliketogreetwhateveris
passedinonthecommandline.Todothat,youshouldknowthatthe
[email protected]
atthefirstelement,wecouldindexitusing$ARGV[0].The
usualidiom,however,istoremovetheelementfromthearrayandthen
dealwithitand/orthrowitway.shiftisusedtogetatthefirst
elementofanarray,thuswewouldwritesomethinglike:
#!/usr/local/bin/perl-w
usestrict;
my$thing=shift(@ARGV);
print"Hello,$thing\n";
[download]
Asitturnsout,Perloffersaconvenientshort-cut.Ifyouuse
shiftoutsideasubroutinecontextwithnoparameters,itwill
implicitlyuse@ARGV,sotheabovecanberewrittenas:
#!/usr/local/bin/perl-w
usestrict;
my$thing=shift;
print"Hello,$thing\n";
[download]
ThisiswillbefamiliartopeopleusedtoUnixshellprogramming.This
isallwellandgood;thescript'sbehaviouriscontrolledby
theparametersappearingonthecommandline.Thereisaproblem,
however,inthatnowaparametermustbesupplied,forifitis
omitted,thescriptwillcoughupaUseofuninitializedvaluein
concatenationerror,andallthatwillbeprintedis"Hello,".
Usingdefaultvalues
Itwouldbenicetobeabletoprovidethescriptwithasensible
defaultvalue,sothatshouldnoparameterbesupplied,itwillbeable
tocontinueanddosomethingreasonable.Forthiswecanusethe||
operator:
#!/usr/local/bin/perl-w
usestrict;
my$thing=shift||'world';
print"Hello,$thing\n";
[download]
Whatthisdoesisassign$thingthevalueofthefirst
parameteronthecommandlineor'world',shouldthecommandlinebe
empty.Ofcourse,sometimesanemptycommandlineisnotreasonable,in
whichcasethebestthingistostopthescriptandprintoutamessage
sothattheusercantakecorrectiveaction:
#!/usr/local/bin/perl-w
usestrict;
my$thing=shiftordie"Nothingspecifiedonthecommandline.\n";
print"Hello,$thing\n";
[download]
Notethatthecorrectidiomsaretosayshift||$valuebut
shiftordie.ReaduponPerl'sprecedencerulestounderstand
why.
There'sanothergotchatobeawareof,ifever0isa
validvaluetopassinonthecommandline:
my$thing=shift||'default';
[download]
...willnotdotherightthingifyoupass0tothescript.
ItboilsdowntowhatPerlconsiderstruth.Itjustso
happensthat0istreatedasfalse,sothelefthandsideofthe
||operatorasawholeisfalse,andthus$thing
windsupbeingassignedthevalueof'default'.
Thereisasimpletwostepprocesswayaroundthis.Firstassignwhat
comesoutofshift.Then,dependingonwhether$thing
isdefined(notwhetheritistrueorfalse,thusside-steppingthe
issue),usethewonderful-but-cryptic||=topossibly
assignto$thing,basedontheoutcomeoftheconditional.
my$thing=shift;
$thing||='default'unlessdefined$thing;
[download]
Introducingcomandlineswitches
Nowsupposingwewantedtomodifythescripttosay"Goodbye"
accordingtowhetherthe-gswitchwasused.Wewouldliketosay
thingslike:
greet
greetsailor
greet-g
greet-g'cruelworld'
LetusfirstconsiderTheWrongWaytodoit:
#!/usr/local/bin/perl-w
usestrict;
my($switch,$thing);
$switch=shift;
if($switchand$switcheq"-g"){
$thing=shift||'world';
}else{
$thing=$switch||shift||'world';
$switch=undefif$switch;
}
print$switch?'Goodbye':'Hello',",$thing\n";
[download]
Theabovecodeisdifficulttounderstand.Itdoes,however,work
accordingtospec.Themainproblemisthatitwillfailtoconsider
-tor-anythingasaswitch,andcomplainthatthe
switchhasnoeffectontheprogram.Forexample,considerwhatgreet
-hharrywillprintout.Evenworse,thecodewillbecomehorribly
obfuscatedshouldthescripthavetodealwithtwo,threeormorecommand
lineswitches.
Obviously,abetterapproachiscalledrequired.Aboveall,itwould
benicenottohavetowriteitoneself,butratherusesomethingthat
existsalready.Thatmustmeanthatpackagesexisttodowhatweneed.
Whatwearelookingforissomethingthatwilllookforswitch-like
instancesonthecommandline,setsomecorrespondingPerlvariablesand
aboveallremovethemfrom@ARGVsothatwedon'thavetobother
withthem.
Whatcanperloffer?
NotethedistinctionbetweenPerlthelanguageandperlthe
interpreter.Asitturnsoutperl,thePerlinterpretercandosomerudimentary
commandlineprocessingallbyitself.Sometimesthisissufficient.All
youhavetodoisfeedtheinterpreterthe-sswitch:
#!/usr/local/bin/perl-sw
usestrict;
usevarsqw/$g/;
my$thing=shift||'world';
print$g?'Goodbye':'Hello',",$thing\n";
[download]
Nowwehaveamuchsmallerscriptthatshouldbeeasierto
understand.Thereis,however,asmallproblemduetointeractionswith
usestrictpragma.The-sfunctionalityharksbackto
beforetheageoflexicalvariables.Itreferstopackagevariablesthat
havetobeexplicitlydeclaredinausevarspragmawhen
strictisinuse.Thisisnotreallyaproblem,exceptthat
ifthescriptisrunwiththe-hswitchandwarningsareswitchedon,
theprogramwillcompletebutitwillspitoutaName"main::h"
usedonlyonce:possibletypo.warningmessage.
Beforeturningawayfrom-sasaviablesolution,consider
theotherfeaturethatPerlprovides.Iftheabovescriptisrunwith
-g,thepackagevariable$gissetto1.Alternatively,
thescriptcouldberunwith-g=foo,inwhichcaseinsteadof
beingsetto1,$gwouldcontain'foo'.Sometimesthislimited
functionalityisenoughtogetthejobdone,andthefactthatyoudon't
havetodragaroundanexternalpackagefilecanbeawinincertain
circumstances.
Itappearsthat
-shassomerathernastysideeffects,whichmeansthatscriptsthatuseitshouldonlybeusedinsafelycontrolledenvironments(ifsuchathingexists).Formoreinformation,readthethread"perl-sisevil?".
getopt:theheavyartillery
MoreUnixculture:thetraditionalwaytoparsecommandlinearguments
inCwasthroughalibrarycallnamedgetoptorgetopts,
shortforgetoptions.ThishasbeencarriedovertoPerlinthe
formofGetopt::StdandGetopt::Longwhicharebundled
inthecoredistribution.
Getopt::Std
Getopt::Stdperformscommandlineprocessingandpulls
outanythingthatresemblesa-letterswitchanditsvalue,leaving
[email protected],
getoptandgetopts.Youalmostalwayswanttousethe
secondvariant.Let'sseewhy:
#!/usr/local/bin/perl-w
usestrict;
useGetopt::Std;
usevarsqw/$opt_g/;
getopt('g');
my$thing=shift||'world';
print$opt_g?'Goodbye':'Hello',",$thing\n";
[download]
Beforegoinganyfurther,thefirstthingtopointoutisthat
Getopt::Stdhasbeenretrofittedtogetaroundtheuncomfortable
useofpackagevariables.Ifyoupassareferencetoahashasthe
secondparametertothegetoptcall,itwillpopulatethe
hash,insteadofusingpackagevariables,whichallowsthescripttobe
rewrittenas:
#!/usr/local/bin/perl-w
usestrict;
useGetopt::Std;
my%args;
getopt('g',\%args);
my$thing=shift||'world';
print$args{g}?'Goodbye':'Hello',",$thing\n";
[download]
Thisscriptwillsilentlyignoreanon-specifiedswitch,which
isusuallyAGoodThing.Thereis,however,aseriousbuglurkingin
thiscode.Trytogetthescripttoprint"Goodbye,foo".It'srather
difficulttodobecausegetoptisgreedy.Whenitsees
aspecifiedswitch,ittrieshardtoassignthatswitchameaningful
value,whichmeanseitherthecharactersfollowingtheswitch(asin
-gparam)orthenextparameteronthecommandline
(asin-gparam).Whichmeansifyouruntheabovescriptas
script-gfoo,$arg{g}willcontain'foo',butthere
willbenothingleftonthecommandline,so$thingwillbe
assignedthedefaultvalueof'world'.
Inordertogetaroundthis"feature",thesecondinterface,via
getoptsshouldbeusedinstead.Inthiscase,thespecification
string('g'intheabove)isinterpreteddifferently.Bydefault,all
lettersspecifybooleanparameters.Toforceaparametertopickup
avalue(i.e.togetthebehaviourwesomuchwantedtoavoid
above),a':'(colon)isappended.Therefore,tomake-g
greedy,itshouldbespecifiedas'g:'.
Thismeansthatallwehavetodointheabovescriptistocall
getoptsinsteadofgetoptandthejobisdone.
Ifyouwanttolookatareal-lifeexampleofcodethat
usesGetopt::Std,youcanlookatascriptIuploaded
herenamedpinger,alittletooldesigned
toscanarangeofIPaddressesviaping.
Getopt::Long
Thatisallwellandgood,butwhathappenswhenyoureimplement
tarin
Perl?Howdoyourememberwhatallthosepeskysinglecharacterswitches
dointhestring-cznTfoo?It'smucheasytounderstandwhat's
goingonwith--create--gzip--norecurse--files-fromfoo
instead.EnterGetopt::Long.
Thismoduleletsyoubuildupaspecificationthatadherestothe
POSIXsyntaxforcommandlineoptions,whichgenerallyintroduces
switcheswiththedouble-dashnotation.Unfortunately,thisprecludes
theuseofsingle-dashswitches(bikeNomadpointsoutthatthisisnottrue.Mybadfornotpayingcloserattention
tothedocumentation).Evenworse,youcannotincludeboth
Getopt::StdandGetopt::Longinthesameprogram,
[email protected].
SinceIoriginallywrotethistutorial,IhaveusedGetopt::Longabitmore(figuredthatIhadtosinceIwrotethis).OnceyouunderstandGetopt::Simple,Getopt::Longisprettyeasytopickup,andhasmuchsophisticationtooffer,onceyouscratchbelowthesurface.
Thatsaid,alloftheprocessinggoesonbehindthescenes.Youcanattachacallbacktodealwiththeprocessingofindividualoptions,butthiscanbecomeunwieldy.Sometimesyouneedmorefine-grainedcontroloftheparsingoftheswitches,astheycomeinonebyone.
Whilethefollowingmoduleisnolongerbeingactivelydeveloped,itisjustwhatyouneedinsomeinstances,becauseitdealswithparsingoptionsonly,andletsyoudealwiththerest.Itturnstheparsinginsideout,andletsyouactonoptionsonthefly,andjustthereforefeelsmorecooperative.Tryit,youmightlikeit.
Getopt::Mixed
Thismoduleshouldcoverallyourcommandline
processingneeds.It'squitesimpletosetup.Firstofallyouneedto
callinitwithaformatstring(akintopackandunpack).Thesetsup
whatcommandlineswitchesaredefined,andwhatvaluestheycantakeon.
Here'sareallifeexamplehoistedfromsomecodeIhavelyingaround:
Getopt::Mixed::init('j=sl:sp=is=st=slogfile>ld>pdate>pperiod>
+pproject>
jtype>t');
[download]
Thisencodesthefollowinginformation:
-j,-sand-ttakeamandatorystringargument.
-ltakesanoptionalstringargument
-ptakesamandatoryintegerargument
--logfileisanaliasfor-l
-d,--dateand--periodareallaliasesfor
-p
undsoweiter.
Prettystraightforwardstuff.ThenextstepistocallnextOption
repeatedlyuntilitfails.Oncethatisdone,youhaveprocessedallthe
switches.UnlikeGetopt::Stdyousetyourdefaultsbeforehand.Ifthe
switchisn'tspecified,thevalueisn'ttouched.Alsonotethatjustbecausea
switchhasamandatoryargumentdoesn'tmeanthatthescriptwillabortif
theswitchdoesn'tappearonthecommandline...it'snottheswitchitself
thatismandatory.Ifthisisrequiredthenyoutestthecorresponding
variableaftertheloopandifitsvalueisundefinedthenyouyanktherug
outfromunderthescript.
Theprocessinglooplookssomethinglikethis:
while(my($option,$value,$pretty)=Getopt::Mixed::nextOption()
+){
OPTION:{
$optioneq'j'anddo{
$Project=$value;
lastOPTION;
};
$optioneq'l'anddo{
$Logfile=$valueif$value;
lastOPTION;
};
#...
}
}
Getopt::Mixed::cleanup();
die"Noprojectspecifiedvia-j.\n"unless$Project;
[download]
Themoduleissmartenoughtorecognise
-jfoo
-jfoo
-j=foo
asallbeingvalidsyntaxesforassigningfootothe
-jswitch.Rememberthelastvariant.It'sthe
easiestwayofpassinginanegativenumberonthecommand
line.Afterall,howshould--offset-30be
interpreted?
Anotherreal-lifeexampleofcode,thistimeusing
Getopt::Mixedcanbefoundatnugid,a
scriptIwrotetomanagelargescalemodifications
ofuidsandgidsofUnixfilesystems.
Wheretofromhere
Thisshouldbeenoughfor95%ofyourbasiccommandlineprocessing
needs.Buteveryonehasadifferentitchtoscratch,andyoushouldbe
awarethatthereisaboatloadofgetoptishpackageshangingouton
CPAN,asasearchwillreveal.Onceyouhavethehangofacoupleit's
prettysimpletopickupanother.
Themostsophisticatedofall,Getopt::Declarecomes,
naturallyenough,fromtheDamian.
Thismodulehasanadvancedmethodforspecifyingexactlywhatarethe
legalvaluesthataswitchmaytake,aswellasprovidingpoddishdescriptions
sothatyoudon'thavetowritesubusage{...}thatexplains
howtousetheprogramcorrectly.
Switchnameidioms
Overtheyears,anumberofconventionshavearisenoverthebestletters
toassigntocommonoperationsthatcropupagainandagaininprogram
design.Thislistattemptstocodifyexistingpractices(updateswelcomed).
Usetheseconventionsandpeoplewillfindyourprogramseasytolearn.
-aProcesseverything(all).
-dDebugmode.Printoutlotsofstuff.
-hHelp.Printoutabriefsummaryofwhatthescriptdoesandwhatitexpects.
-iInputfile,orincludefile
-lNameoflogfile
-oNameofoutputfile
-qQuiet.Printoutnothing.
-vVerbose.Printoutlotsofstuff.
Andnowyouknowallyouneedtoknowaboutcommandlineprocessing.
Havefun!
update:Tipo'thehattopetralforpointingout
thenodeonGetopt::Declare,-handabetter
Damianlink.Tipo'thehattoAlbannachforreminding
meaboutthe"passing0onthecommandline"bugaboo,and
toOeufMayoregardingpassingnegativenumbers.
CommentonParsingyourscript'scommandlineSelectorDownloadCode
Repliesarelisted'BestFirst'.
Re:Parsingyourscript'scommandline
bybikeNomad(Priest)onJun14,2001at06:35 UTC
Nicetutorial.Oneminordisagreement,though:Getopt::Longisquitehappywithsingle-characterswitches.Ifyouwanttobundlethem(asin,'-vax'meansthesameas'-v-a-x'),youhavetocall:Getopt::Long::Configure("bundling");
[download]
[reply][d/l]
Re:Parsingyourscript'scommandline
bymugwumpjism(Hermit)onJun14,2001at14:46 UTC
YoushouldalsochecktoseeifyouroptionislistedintheGNUCodingStandardsOptionTable.Don'tforgettosupport--helpand--version!
Otherthanthat,niceintro.[reply]
Re:Re:Parsingyourscript'scommandline
byxphase_work(Pilgrim)onJun14,2001at18:38 UTC
ThatstatementonlyappliestoGNU/Linuxsystems,oratleastsystems
thatusetheGNUBinutils.MostcommercialUNIXvendorsdon'thave
longoptionsupportintheirBinutils.SunandHP'sversionsoftardon't
supportlongarguments,butFreeBSDandLinuxsupportbothformsof
arguments.
Whilethechoiceofwhichargumentsyourprogramsacceptisyourchoice,
manypeoplechoosetofollowthestandardtheirOSvendoruses.
Ithinkthatthetableshowingonlytheshortargumentsisgood
becauseshortargumentsismoreofastandardthenGNU-Stylearguments,
butIthinkthatincludingalinktoGNUCodingStandardsOptionTable,
withanexplainationthattheseareusedmainlyonGNU/LinuxorGNUBinutils
systemswouldbeuseful.
-xPhase[reply]
Re:Re:Re:Parsingyourscript'scommandline
bymugwumpjism(Hermit)onJun14,2001at23:20 UTC
Ah,butthisisPerl,you'resupposedtobethinking
crossplatform.AndwhatismorecrossplatformthanGNU?
I'drecommendlookingatthetable,andusingwhat'son
thereunlessyouhaveagoodreasonnotto.[reply]
Re:Parsingyourscript'scommandline
byNot_a_Number(Prior)onAug14,2003at18:07 UTC
Verynice,++
However,Ihaveasmallquestiononthissnippet:
my$thing=shift;
$thing||='default'unlessdefined$thing;
[download]
Surelythe||isredundanthere?
my$thing=shift;
$thing='default'unlessdefined$thing;
[download]
Thisseemstodothejobjustaswell?
OramImissingsomething?
thx
dave[reply][d/l][select]
Re:Re:Parsingyourscript'scommandline
byyosefm(Friar)onSep04,2003at11:48 UTC
Thisisbecause$thingcouldbedefinedbutzeroandwedon'twanttooverwriteaperfectlyvalidzerofromthecommandline.[reply]
Re:Re:Re:Parsingyourscript'scommandline
byNot_a_Number(Prior)onSep04,2003at20:17 UTC
Er...
I'mafraidIdon'tunderstand.Underwhatcircumstancesdoes:
$thing='default'unlessdefined$thing;
notworkfor$thing==0?I'mconfused.Couldyoushowmesomecodewherethebehaviouroftheabovediffersfrom:
$thing||='default'unlessdefined$thing;
Thanksinadvance,
dave
[reply][d/l][select]
Re^3:Parsingyourscript'scommandline
byJadeNB(Chaplain)onSep07,2008at20:16 UTC
Thisisbecause$thingcouldbedefinedbutzeroandwedon'twanttooverwriteaperfectlyvalidzerofromthecommandline.
AsNot_a_Numberpointsout,thesyntaxEXPRunlessdefined$thingwilldonothingatall*if$thingisdefined,whetherit'strueorfalse.Thatis,ifweareexecutingEXPR,then$thingisguaranteedundefined,hencefalse;so$thing||='default'isguaranteedtobethesameas$thing='default'.
Itseemsreasonabletoguessthatwhathappenedisthatthecoderoriginallyhad$thing||='default'insomeoldcode,discovered(asyoumention)thatitdoesn'tworkwhen$thingisfalse-but-defined,andaddedthedefinedcheckwithoutrealisingthatitmade||=redundant.
Ofcourse,amerefiveyearslater,wehavethewonderful//=(CstyleLogicalDefinedOr)insteadtosaveusthispain.
UPDATE(the*'dstatementabove—sorry,Idon'tknowhowtodofootnotes):Onfurtherthought,it'snotquitetruethatEXPRunlessdefined$thingwilldonothingif$thingisdefined.AmongwhatIsupposearemanyothersubtlecases,iftheunlessisthelastlineinasubroutine,it'llmakethesubroutinereturn1when$thingisdefined.Forexample,after
our$a=1;
subb{0unlessdefined$a}
subc{}
my$b=b;
my$c=c;
[download]
wehavethat$b=1but$cisundefined.[reply][d/l][select]
Re:Parsingyourscript'scommandline
byAnonymousMonkonMar04,2005at14:42 UTC
Verynicetutorial.Helpedmealot.Exspeciallyididn'tsawanoteintheCPANGetOpt:Stddocsthatsaid"GetOpsstripsofallparametersfrom@ARGVandleavestherest".
Butthatsreallyimportantifyouwanttouse<>toprocesssomefilesspecifiedonthecommand-line.
Sothanxforthework=)
GreetingsFromMunich,
GrandApeiron[reply]
Backto
Tutorials
LogIn?
Username:
Password:
rememberme
What'smypassword?
CreateANewUser
DomainNodelet?
www.com|www.net|www.org
NodeStatus?
nodehistoryNodeType:perltutorial[id://88222]help
Chatterbox?
andallisquiet...
HowdoIusethis?|OtherCBclients
OtherUsers?
OthersscrutinizingtheMonastery:(4)GrandFather
eyepopslikeamosquito
Tux
Bod
Asof2022-10-2222:05GMT
Sections?
SeekersofPerlWisdom
CoolUsesforPerl
Meditations
PerlMonksDiscussion
CategorizedQ&A
Tutorials
ObfuscatedCode
PerlPoetry
PerlNews
about
Information?
PerlMonksFAQ
GuidetotheMonastery
What'sNewatPerlMonks
Voting/ExperienceSystem
Tutorials
Reviews
Library
PerlFAQs
OtherInfoSources
FindNodes?
NodesYouWrote
SuperSearch
ListNodesByUsers
NewestNodes
RecentlyActiveThreads
SelectedBestNodes
BestNodes
WorstNodes
SaintsinourBook
Leftovers?
TheSt.LarryWallShrine
BuyPerlMonksGear
OfferingPlate
Awards
RandomNode
Quests
Craft
Snippets
CodeCatacombs
EditorRequests
blogs.perl.org
Perlsphere
PerlWeekly
Perl.com
PerlJobs
PerlMongers
PerlDirectory
Perldocumentation
MetaCPAN
CPAN
VotingBooth?
Mypreferredwaytoholiday/vacationis:
Visitforeigncountries/cities Relaxataresort Takeacruise Gotovisitfarawayfamily Getawayfromcivilization(e.g.camping,hiking,etc.) Wanderaroundmyowncountry/region(byanypreferredmeansofconveyance) Workonasideproject(e.g.homeimprovement,side-hustle,etc.) Digitalentertainment,astockedfridge,andbeingavoluntaryshut-in What'saholiday/vacation? Other(pleasecomment)Results(67votes).Checkoutpastpolls.
Notices?
PerlMonksparthenogeneticallyspawnedbyTimVroom.
PerlMonkswentonacoupledates,andthendecidedtoshackupwith
ThePerlFoundation.
BeefyBoxesandBandwidthGenerouslyProvidedby
pairNetworks
BuiltwiththePerlprogramminglanguage.