Perl One-Liners · Perl One-Liners 130 Programs That Get Things Done Peteris Krumins Published by...
Transcript of Perl One-Liners · Perl One-Liners 130 Programs That Get Things Done Peteris Krumins Published by...
PerlOne-Liners130ProgramsThatGetThingsDone
PeterisKrumins
PublishedbyNoStarchPress
AbouttheAuthor
PeterisKruminsisaprogrammer,systemsadministrator,blogger,andall-aroundhacker.Heiscurrentlyrunninghisowncompany,Browserling,whichfocusesoncross-browsertesting.Hehasself-publishedthreebooksonessentialUNIXtools,andheenjoysopen-sourcinghundredsofsmallprojectsonGitHub.
Findhiswebsiteandblogathttp://www.catonmat.net/,follow@pkruminson
Twitter,andseehisopensourceprojectsathttp://github.com/pkrumins/.
AbouttheTechnicalReviewer
AlastairMcGowan-DouglaslivesinRugbyintheUK.HehasbeenaPerldevelopersince2008andisnowstuckwritingPHPforaliving.HisfavoritepastimeatworkiswritingPerlscriptsforinternalusetoencourageotherstoembracethelanguage.AlsoaJavaScriptdeveloperandGitaficionado,hisrantingsandmusingsonthesevarioussubjectscanbefoundathttp://altreus.blogspot.com/.
Acknowledgments
I’dliketothankEricPementforinspiringmetowritethisbook;BillPollockforgivingmetheopportunitytopublishitatNoStarchPress;RileyHoffmanandLaurelChunforworkingwithmetomakeitperfect;AlastairMcGowan-Douglasforhistechnicalreview;andDavidPrecious,GaborSzabo,JimDavis,ChrisFedde,AndyLester,JohnD.Cook,JonathanScottDuff,andJeremyMatesforreviewingthebookandmakinggreatsuggestionsforimprovements.I’dalsoliketothankeveryonewhohelpedmeonthe#perlIRCchannelonfreenode.IfIforgotanyone,I’msorry,butthanksforhelpingmetogetthisbookwritten!
Chapter1.IntroductiontoPerlOne-Liners
Perlone-linersaresmallandawesomePerlprogramsthatfitinasinglelineofcode.Theydoonethingreallywell—likechanginglinespacing,numberinglines,performingcalculations,convertingandsubstitutingtext,deletingandprintingspecificlines,parsinglogs,editingfilesin-place,calculatingstatistics,carryingoutsystemadministrationtasks,orupdatingabunchoffilesatonce.Perlone-linerswillmakeyouashellwarrior:whattookyouminutes(orevenhours)tosolvewillnowtakeyouonlyseconds!
Inthisintroductorychapter,I’llshowyouwhatone-linerslooklikeandgiveyouatasteofwhat’sintherestofthebook.ThisbookrequiressomePerlknowledge,butmostoftheone-linerscanbetweakedandmodifiedwithoutknowingthelanguageindepth.
Let’slookatsomeexamples.Here’sone:
perl -pi -e 's/you/me/g' file
Thisone-linerreplacesalloccurrencesofthetextyouwithmeinthefilefile.Veryusefulifyouaskme.Imagineyou’reonaremoteserverandyouneedtoreplacetextinafile.Youcaneitheropenthefileinatexteditorandexecutefind-replaceorsimplyperformthereplacementthroughthecommandlineand,bam,bedonewithit.
Thisone-linerandothersinthisbookworkwellinUNIX.I’musingPerl5.8torunthem,buttheyalsoworkinnewerPerlversions,suchasPerl5.10andlater.Ifyou’reonaWindowscomputer,you’llneedtochangethemalittle.Tomakethisone-linerworkonWindows,swapthesinglequotesfordoublequotes.TolearnmoreaboutusingPerlone-linersonWindows,seeAppendixB.
I’llbeusingPerl’s-ecommand-lineargumentthroughoutthebook.Itallows
youtousethecommandlinetospecifythePerlcodetobeexecuted.Inthepreviousone-liner,thecodesays“dothesubstitution(s/you/me/gcommand)andreplaceyouwithmeglobally(/gflag).”The-pargumentensuresthatthecodeisexecutedoneverylineofinputandthatthelineisprintedafterexecution.The-iargumentensuresthatfileiseditedin-place.Editingin-placemeansthatPerlperformsallthesubstitutionsrightinthefile,overwritingthecontentyouwanttoreplace.Irecommendthatyoualwaysmakeabackupofthefileyou’reworkingwithbyspecifyingthebackupextensiontothe-iargument,likethis:
perl -pi.bak -e 's/you/me/g' file
NowPerlcreatesafile.bakbackupfilefirstandonlythenchangesthecontentsoffile.
Howaboutdoingthissamereplacementinmultiplefiles?Justspecifythefilesonthecommandline:
perl -pi -e 's/you/me/g' file1 file2 file3
Here,Perlfirstreplacesyouwithmeinfile1andthendoesthesameinfile2andfile3.
Youcanalsoperformthesamereplacementonlyonlinesthatmatchwe,assimplyasthis:
perl -pi -e 's/you/me/g if /we/' file
Here,youusetheconditionalif /we/toensurethats/you/me/gisexecutedonlyonlinesthatmatchtheregularexpression/we/.
Theregularexpressioncanbeanything.Sayyouwanttoexecutethesubstitutiononlyonlineswithdigitsinthem.Youcouldusethe/\d/regularexpressiontomatchnumbers:
perl -pi -e 's/you/me/g if /\d/' file
Howaboutfindingalllinesinafilethatappearmorethanonce?
perl -ne 'print if $a{$_}++' file
Thisone-linerrecordsthelinesyou’veseensofarinthe%ahashandcountsthenumberoftimesitseesthelines.Ifithasalreadyseentheline,thecondition$a{$_}++istrue,soitprintstheline.Otherwiseit“automagically”createsanelementthatcontainsthecurrentlineinthe%ahashandincrementsitsvalue.The$_specialvariablecontainsthecurrentline.Thisone-lineralsousesthe-ncommand-lineargumenttoloopovertheinput,butunlike-p,itdoesn’tprintthelinesautomatically.(Don’tworryaboutallthecommand-lineargumentsrightnow;you’lllearnaboutthemasyouworkthroughthisbook!)
Howaboutnumberinglines?Supersimple!Perl’s$.specialvariablemaintainsthecurrentlinenumber.Justprintittogetherwiththeline:
perl -ne 'print "$. $_"' file
Youcandothesamethingbyusingthe-pargumentandmodifyingthe$_variable:
perl -pe '$_ = "$. $_"' file
Here,eachlineisreplacedbythestring"$. $_",whichisequaltothecurrentlinenumberfollowedbythelineitself.(Seeone-liner3.1onpage17forafullexplanation.)
Ifyouomitthefilenameattheendoftheone-liner,Perlreadsdatafromstandardinput.Fromnowon,I’llassumethedatacomesfromthestandardinputanddropthefilenameattheend.Youcanalwaysputitbackifyouwanttorunone-linersonwholefiles.
Youcanalsocombinetheprevioustwoone-linerstocreateonethatnumbersonlytherepeatedlines:
perl -ne 'print "$. $_" if $a{$_}++'
AnotherthingyoucandoissumthenumbersineachlineusingthesumfunctionfromtheList::UtilCPANmodule.CPAN(ComprehensivePerlArchiveNetwork;http://www.cpan.org/)isanarchiveofover100,000reusablePerl
modules.List::UtilisoneofthemodulesonCPAN,anditcontainsvariouslistutilityfunctions.Youdon’tneedtoinstallthismodulebecauseitcomeswithPerl.(It’sinPerlcore.)
perl -MList::Util=sum -alne 'print sum @F'
The-MList::Utilcommand-lineargumentimportstheList::Utilmodule.The=sumpartofthisone-linerimportsthesumfunctionfromtheList::Utilmodulesothattheprogramcanusethefunction.Next,-aenablestheautomaticsplittingofthecurrentlineintofieldsinthe@Farray.Thesplittinghappensonthewhitespacecharacterbydefault.The-largumentensuresthatprintoutputsanewlineattheendofeachline.Finally,sum @Fsumsalltheelementsinthe@Flist,andprintprintstheresultfollowedbyanewline(whichIaddedwiththe-largument).(Seeone-liner4.2onpage30foramoredetailedexplanation.)
Howaboutfindingthedate1299daysago?Trythis:
perl -MPOSIX -le
'@t = localtime; $t[3] -= 1299; print scalar localtime mktime @t'
Iexplainthisexampleindetailinone-liner4.19(page41),butbasicallyyoumodifythefourthelementofthestructurereturnedbylocaltime,whichhappenstobedays.Yousimplysubtract1299daysfromthecurrentdayandthenreassembletheresultintoanewtimewithlocaltime mktime @tandprinttheresultinthescalarcontexttodisplayhuman-readabletime.
Howaboutgeneratinganeight-letterpassword?Hereyougo:
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
The"a".."z"generatesalistoflettersfromatoz(foratotalof26letters).Thenyourandomlychoosealettereighttimes!(Thisexampleisexplainedindetailinone-liner5.4onpage51.)
OrsupposeyouwanttofindthedecimalnumberthatcorrespondstoanIPaddress.Youcanuseunpacktofinditreallyquickly:
perl -le 'print unpack("N", 127.0.0.1)'
Thisone-linerusesav-string,whichisaversionliteral.V-stringsofferawaytocomposeastringwiththespecifiedordinals.TheIPaddress127.0.0.1istreatedasav-string,meaningthenumbers127,0,0,1areconcatenatedtogetherintoastringoffourcharacters,wherethefirstcharacterhasordinalvalue127,thesecondandthirdcharactershaveordinalvalues0,andthelastcharacterhasordinalvalue1.Next,unpackunpacksthemtoasingledecimalnumberin“network”(big-endian)order.(Seeone-liner4.27onpage45formore.)
Whataboutcalculations?Let’sfindthesumofthenumbersinthefirstcolumninatable:
perl -lane '$sum += $F[0]; END { print $sum }'
Thelinesareautomaticallysplitintofieldswiththe-aargument,[email protected],$F[0],isthefirstcolumn,soyousimplysumallthecolumnswith$sum += $F[0].WhenthePerlprogramfinishes,itexecutesanycodeintheENDblock,which,inthiscase,printsthetotalsum.Easy!
Nowlet’sfindouthowmanypacketshavepassedthroughiptablesrules:
iptables -L -nvx | perl -lane '$pkts += $F[0]; END { print $pkts }'
Theiptablesprogramoutputsthepacketsinthefirstcolumn.Allyouhavetodotofindouthowmanypacketshavepassedthroughthefirewallrulesissumthenumbersinthefirstcolumn.Althoughiptableswilloutputtableheadersaswell,youcansafelyignorethesebecausePerlconvertsthemtozeroforthe+=operation.
Howaboutgettingalistofallusersonthesystem?
perl -a -F: -lne 'print $F[4]' /etc/passwd
Combining-awiththe-Fargumentletsyouspecifythecharacterwherelinesshouldbesplit,which,bydefault,iswhitespace.Here,yousplitlinesonthecoloncharacter,therecordseparatorof/etc/passwd.Next,youprintthefifthfield,$F[4],whichcontainstheuser’srealname.
Ifyouevergetlostwithcommand-linearguments,rememberthatPerlcomeswithafantasticdocumentationsystemcalledperldoc.Typeperldoc perlrunatthecommandline.ThiswilldisplaythedocumentationabouthowtorunPerlandallthecommand-linearguments.It’sveryusefulwhenyousuddenlyforgetwhichcommand-lineargumentdoeswhatandneedtolookitupquickly.Youmayalsowanttoreadperldocperlvar,whichexplainsvariables;perldocperlop,whichexplainsoperators;andperldocperlfunc,whichexplainsfunctions.
Perlone-linersletyouaccomplishmanytasksquickly.You’llfindover130one-linersinthisbook.Readthem,trythem,andsoonenoughyou’llbethelocalshellwizard.(Justdon’ttellyourfriends—unlessyouwantcompetition.)
Enjoy!
Chapter2.Spacing
Inthischapter,welookatvariousone-linersthatchangelineandwordspacing,performingsuchtasksasdouble-andtriple-spacinglinesinafile,removingblanklines,anddouble-spacingwords.You’llalsolearnaboutvariouscommand-linearguments,suchas-p,-e,-n,andspecialvariables,suchas$_and$\.
2.1Double-spaceafile
perl -pe '$\ = "\n"' file
Thisone-linerdouble-spacesafile.Ineedtoexplainthreethingshere:the-pand-ecommand-lineoptionsandtheshort$\ = "\n"Perlprogram.
Usethe-eoptiontoenteraPerlprogramdirectlyatthecommandline.Typicallyyouwon’twanttocreatesourcefilesforeverysmallprogram;with-eyoucaneasilywriteaprogramdirectlyatthecommandlineasaone-liner.Inthiscase,theentirePerlprogramcontainedinthisone-lineris$\ = "\n".Besuretousesinglequotes(')aroundtheprogram,oryourshellwillinterpretthingslike$\asshellvariables,whichhavenovalue,effectivelyremovingthem!
Nowlet’slookatthe-pswitch.Specifying-ptellsPerltoassumethefollowinglooparoundyourprogram:
while (<>) {
# your program goes here (specified by -e)
} continue {
print or die "-p failed: $!\n";
}
Broadlyspeaking,thisconstructloopsoveralltheinput,executesyourcode,and
printsthevalueof$_(theprintstatementprintsthevalueof$_),whichallowsyoutomodifyallorsomelinesoftheinputquickly.The$_variableisaspecialvariablethatgetsreplacedwiththecurrentlineoftext.Itcanbereplacedwithotherstuffaswell.You’lllearnallabout$_asyouworkthroughthebook.(SeeAppendixAforasummaryofitsusecases.)
Butunderstandingwhatisgoingoninthisloopinmoredetailisimportant.First,thewhile (<>)looptakeseachlinefromthestandardinputandputsitinthe$_variable.Next,thecodespecifiedby-eisexecuted,followedbytheprint ordieportion.
Thecontinuestatementexecutestheprint or diestatementaftereachline,whichattemptstoprintthecontentsofthe$_variable.Iftheattemptfails(forexample,theterminalisnotwritableorstandardoutputhasbeenredirectedtosomethingthatisn’twritable),diemakesPerlexit(die)withanerrormessage.
Inthisone-liner,thecodespecifiedby-eis$\ = "\n",sotheprogramthatPerlexecuteslookslikethis:
while (<>) {
$\ = "\n";
} continue {
print or die "-p failed: $!\n";
}
ThisPerlprogramreadseachlineintothe$_variableandthensets$\toanewlineandcallsprint.Anotherspecialvariableis$\.ItissimilartotheORS(OutputRecordSeparator)variableinAwkinthatitisappendedaftereveryprintoperation.Aprintstatementwithnoargumentsprintsthecontentsof$_andappends$\attheendoftheoutput.Asaresult,eachlineisprintedunmodified,followedbythe$\,whichwassettonewline.Theinputisnowdouble-spaced.
Infact,youactuallydonotneedtoset$\tonewlineforeveryline;youcansetitjustonceatthebeginningoftheprogram:
perl -pe 'BEGIN { $\ = "\n" }' file
Thisone-linersets$\tothenewlinecharacterjustoncebeforePerldoesanythingintheBEGINcodeblock.TheBEGINblockisaspecialcodeblockthatisexecutedbeforeeverythingelseinaPerlprogram.Here’swhattheexpandedPerlprogramlookslike,anditworksexactlythesamewayasthepreviousone-liner:
BEGIN { $\ = "\n" }
while (<>) {
} continue {
print or die "-p failed: $!\n";
}
Hereisanotherwaytodouble-spaceafile.Thisone-linerappendsanothernewlinecharacterattheendofeachlineandthenprintstheline:
perl -pe '$_ .= "\n"' file
Thisone-linerisequivalentto
while (<>) {
$_ = $_ . "\n"
} continue {
print or die "-p failed: $!\n";
}
Writing$_ = $_ . "\n"isthesameaswriting$_ .= "\n".Thisexpressionsimplyconcatenates$_with"\n".(Theperiod(.)isthestringconcatenationoperator.)
Butprobablythecleanestwaytodouble-spaceafileistousethesubstitutionoperators:
perl -pe 's/$/\n/' file
Thisone-linerreplacestheregularexpression$thatmatchestheendofalinewithanewline,effectivelyaddinganewlineattheend.
Ifyou’rerunningPerl5.10orlater,youcanusethesayoperator.Thesayoperatoractsmuchlikeprint,butitalwaysaddsanewlineattheendofthe
line.InPerl5.10,thissameone-linercanbewrittenlikethis:
perl -nE 'say' file
The-Ecommand-lineargumentworksexactlythesamewayasthe-ecommand-lineargument,butitalsoenablesPerl5.10features,includingthesayoperator.The-nargumentissimilarto-p,butyouhavetoprintthelineyourself.(Iexplainthe-nargumentinmoredetailinone-liner2.6.)Thisone-linerprintstheline,followedbyanothernewlinethat’sappendedbythesayoperator.
Forexample,ifafilecontainsfourlines:
line1
line2
line3
line4
runninganyoftheseone-linersoutputsthefollowing:
line1
line2
line3
line4
Inthesefirstfewexamples,Ipassedafilenameasthelastargumenttotheone-liners.WhenIdothat,theone-linersoperateonthecontentsofthatfile.IfIdidn’tpassafilenametotheone-liners,they’doperateonthedatafromthestandardinput.FromnowonIwon’tspecifyafileattheendoftheone-liners,butyoucanalwaysadditbackifyouwanttoruntheone-linersonfiles.Whenwritingone-liners,it’sagoodideatoquicklytestifthey’recorrectbytypingsomethingdirectlytothestandardinput.Thenwhenyou’resuretheone-linerworks,youcanpassoneormorefilenamesattheend.
Again,don’tforgetaboutPerl’shandydocumentationsystem,perldoc.Justtypeperldoc perlrunatthecommandlinetodisplayinformationabouthowtorunPerlandallthecommand-linearguments.
2.2Double-spaceafile,excludingtheblanklines
2.2Double-spaceafile,excludingtheblanklines
perl -pe '$_ .= "\n" unless /^$/'
Thisone-linerdouble-spacesalllinesthatarenotcompletelyemptybyappendinganewlinecharacterattheendofeachnonblankline.Theunlessmeans“ifnot,”andunless /^$/means“ifnot‘beginningthenendofline.’”Thecondition“beginningthenendofline”istrueonlyforblanklines.
Here’showthisone-linerlookswhenexpanded:
while (<>) {
unless (/^$/) {
$_ .= "\n"
}
} continue {
print or die "-p failed: $!\n";
}
Hereisabettertest,whichtakesintoaccountspacesandtabsonaline:
perl -pe '$_ .= "\n" if /\S/'
Here,thelineismatchedagainst\S—aregularexpressionsequencethatistheinverseof\s,whichmatchesanywhitespacecharacter(includingtab,verticaltab,space,newline,andcarriagereturn).Theinverseof\sisanynonwhitespacecharacter.Theresultisthateverylinewithatleastonenonwhitespacecharacterisdouble-spaced.
2.3Triple-spaceafileYoucanalsotriple-spaceafilesimplybyoutputtingmorenewlinesattheendofeachline:
perl -pe '$\ = "\n\n"'
Or
perl -pe '$_ .= "\n\n"'
perl -pe '$_ .= "\n\n"'
Or
perl -pe 's/$/\n\n/'
Theseone-linersaresimilartothefirstone-linerinthischapter,exceptthattwonewlinesareappendedaftereachline.
2.4N-spaceafile
perl -pe '$_ .= "\n"x7'
Thisone-linerinsertssevennewlinesaftereachline.NoticehowI’veused"\n"x 7torepeatthenewlinecharacterseventimes.ThexoperatorrepeatsthevalueontheleftNtimes.
Forexample,theline
perl -e 'print "foo"x5'
printsfoofoofoofoofoo.
Asasidenote,sometimeswhenyouneedtogenerateacertainamountofdata,thexoperatorcomesinreallyhandy.Forexample,togenerate1KBofdata,youcoulddothis:
perl -e 'print "a"x1024'
Thisone-linerprintstheacharacter1024times.
2.5Addablanklinebeforeeveryline
perl -pe 's/^/\n/'
Thisone-linerusesthes/regex/replace/operator.Itsubstitutesthegivenregularexpressionwiththereplacement.Inthisone-liner,theoperatoris
s/^/\n/,theregularexpressionis^,andthereplacementis\n.The^patternmatchesthebeginningpositionofthetext,andthesoperatorreplacesitwith\n,anewline.Asaresult,thenewlinecharacterisinsertedbeforetheline.Toinsertsomethingelsebeforetheline,simplyreplace\nwiththebittobeinserted.
2.6Removeallblanklines
perl -ne 'print unless /^$/'
Thisone-linerusesthe-nflag,whichtellsPerltoassumeadifferentloop,otherthan-p,aroundtheprogram:
while (<>) {
# your program goes here
}
ComparethislooptotheonethatPerlassumeswhenyouspecify-p,andyou’llseethatthisloophasnocontinue { print or die }part.Inthisloop,eachlineisreadbythediamondoperator<>andisplacedinthespecialvariable$_,butit’snotprinted!Youhavetoprintthelineyourself—ausefulfeatureifyouwanttoprint,modify,ordeletelinesselectively.
Inthisone-liner,thecodeisprint unless /^$/,sotheentirePerlprogrambecomes
while (<>) {
print unless /^$/
}
Unravelingthisabitfurther,yougetthis:
while (<>) {
print $_ unless $_ =~ /^$/
}
Thisone-linerprintsallnonblanklines.(Yousawthe/^$/regularexpressioninone-liner2.2onpage11.)
Thisone-lineralsoremovesallblanklines:
Thisone-lineralsoremovesallblanklines:
perl -lne 'print if length'
Thisone-linerusesthe-lcommand-lineargument,whichautomaticallychompstheinputline(basicallyremovesthenewlineattheend)andappendsitbackattheendofthelinewhenprinting.Thecodespecifiedtothe-eargumentis'print if length',whichsays“printthelineifithassomelength.”Emptylineshavealengthof0,sothey’renotprinted(0isafalsevalueinPerl,sotheif lengthconditionevaluatestofalse).Allotherlineshavelengthandareprinted.Without-l,thestringwouldstillhavethenewlineattheendandthusbe1or2characterslong![1]
Here’sanotherone-linertoremoveallblanklines:
perl -ne 'print if /\S/'
Thisone-linerbehavesslightlydifferentlyfromtheprevioustwo.Bothprintunless /^$/andprint if lengthalsoprintthelinesthatconsistofonlyspacesand/ortabs.Suchlinesappeartobeemptytotheeye,andyoumaywanttofilterthem.Thisone-lineruses\S(explainedinone-liner2.2onpage11),aregularexpressionsequencethatmatchesnonblankcharacters.Linescontainingonlyspacesand/ortabsdon’tmatch\Sandthereforearenotprinted.
Asyoucansee,youcanwritethesameprograminmanydifferentways.Infact,Perl’smottoisThere’sMoreThanOneWayToDoIt,whichisabbreviatedasTIMTOWTDIandpronounced“TimToady.”(Funtrivia:LarryWall,theinventorofPerl,usesthehandle@TimToadyonTwitterandIRC.)
2.7Removeallconsecutiveblanklines,leavingonlyone
perl -00 -pe ''
Thisone-linerisreallytricky,isn’tit?First,itdoesn’thaveanycode!The-eisempty.Next,ithasasilly-00command-lineoptionthatturnsparagraphslurp
modeon,meaningPerlreadstextparagraphbyparagraph,ratherthanlinebyline.(Aparagraphistextbetweentwoormorenewlines.)Theparagraphisputinto$_,andthe-poptionprintsitout.
Youcanevenwritethisinashorterfashion:
perl -00pe0
Here,thecodespecifiedto-eis0,whichdoesnothing.
Thisisoneofmyfavoriteone-linersbecauseifyouhaven’tseenitbefore,itcanbetrickytofigureout,andIlovemindgames.(There’snocodespecifiedto-e!Howcanitpossiblydosomething?)
2.8Compress/expandallblanklinesintoNconsecutivelinesSayyouhaveafilewithtwoblanklinesaftereachparagraph,andyouwishtoexpandthelinespacingbetweentheparagraphstothreelines.Todoso,youcansimplycombineone-liners2.4and2.7likethis:
perl -00 -pe '$_ .= "\n"x2'
Thisone-linerslurpslinesparagraph-wiseviathe-00optionandthenappendsthreenewlinecharactersaftereachparagraph.Thecode"\n"x2printstwonewlines,whichareaddedtotheblanklinealreadyattheendoftheparagraph.
Inasimilarvein,youcanalsoreducethespacingbetweenparagraphs.Sayyou’vegotafilethatforsomecrazyreasonhastenblanklinesbetweenparagraphs,andyouwanttocompresstheseblanklinestojustthree.Youcanusethesameone-lineragain!
2.9Double-spacebetweenallwords
perl -pe 's/ / /g'
Here,youusethesubstitutionoperatorstoreplaceonespace“”withtwospaces“”globallyoneachline(the/gflagmakesthereplacementglobal),andyou’redone.It’sthatsimple!
Here’sanexample.Let’ssayyouhavethislineoftext:
this line doesn't have enough whitespace!
Runningthisone-linerincreasesthespacingbetweenwords:
this line doesn't have enough whitespace!
2.10Removeallspacingbetweenwords
perl -pe 's/ +//g'
Thisone-linerusesthe“+”regularexpressiontomatchoneormorespaces.Whenitfindsamatch,itsubstitutesitwithnothing,globally,whichdeletesallspacesbetweenwords.
Ifyoualsowanttogetridoftabsandotherspecialcharactersthatmightaddspacing,usethe\s+regularexpression,whichmeans“matchaspace,atab,averticaltab,anewline,oracarriagereturn”:
perl -pe 's/\s+//g'
Here’sanexample.Let’ssayyouhavethislineoftext:
this line has too much whitespace said cowboy neal
Runningthisone-linerremovesallspaces:
thislinehastoomuchwhitespacesaidcowboyneal
2.11Changeallspacingbetweenwordstoonespace
perl -pe 's/ +/ /g'
Thisone-linerissimilartothepreviousone,exceptthatitreplacesoneormorespaceswithjustonespace.
Forexample,ifyouhavethisline:
this line has really messed-up spacing
runningthisone-linernormalizesthespacingbetweenwordstoonespace:
this line has really messed-up spacing
2.12Insertaspacebetweenallcharacters
perl -lpe 's// /g'
Hereyoumatchseeminglynothingandreplaceitwithasinglespace.Thenothingnessactuallymeans“matchbetweencharacters,”withtheresultthatyouinsertaspacebetweenallcharacters.(Thematchingincludesthebeginningandendofthetext.)
Forexample,giventhisline:
today was a great day
runningthisone-linerproducesthisresult:
t o d a y w a s a g r e a t d a y
Itmightbedifficulttoseewhereallthespacesareadded,solet’sillustratethatbymodifyingthisone-linertoinsertacolonbetweenallcharacters:
perl -lpe 's//:/g'
Thiswilloutput:
:t:o:d:a:y: :w:a:s: :a: :g:r:e:a:t: :d:a:y:
Asyoucansee,spaces(orcolons)arealsoinsertedatthebeginningandendofthetext.Alsonotethattheexistingspacescountascharacters,sothey’retriple-spaced.
[1]Windowsusestwocharactersforthenewline.
Chapter3.Numbering
Inthischapter,we’lllookatvariousone-linersfornumberinglinesandwords,andyou’llgettoknowthe$.specialvariable.You’llalsolearnaboutPerlgolfing,a“sport”thatinvolveswritingtheshortestPerlprogramtogetataskdone.
3.1Numberalllinesinafile
perl -pe '$_ = "$. $_"'
AsIexplainedinone-liner2.1(page7),-ptellsPerltoassumealooparoundtheprogram(specifiedby-e)thatreadseachlineofinputintothe$_variable,executestheprogram,andthenprintsthecontentsofthe$_variable.
Thisone-linersimplymodifies$_byprependingthe$.variabletoit.Thespecialvariable$.containsthecurrentlinenumberoftheinput.Theresultisthateachlinehasitslinenumberprepended.
Similarly,youcanalsousethe-nargumentandprintthestring"$. $_",whichisthecurrentlinenumberfollowedbytheline:
perl -ne 'print "$. $_"'
Sayafilecontainsthreelines:
foo
bar
baz
Runningthisone-linernumbersthem:
1 foo
2 bar
2 bar
3 baz
3.2Numberonlynon-emptylinesinafile
perl -pe '$_ = ++$x." $_" if /./'
Hereyouemployan“actionifcondition”statementthatexecutesanactiononlyiftheconditionistrue.Inthiscase,theconditionistheregularexpression/./,whichmatchesallcharactersotherthannewline(thatis,itmatchesanon-emptyline).Theaction$_ = ++$x." $_"prependsthevariable$xincrementedbyonetothecurrentline.Becauseyou’renotusingthestrictpragma,$xiscreatedautomaticallythefirsttimeit’sincremented.
Theresultisthatateachnon-emptyline$xisincrementedbyoneandprependedtothatline.Nothingismodifiedattheemptylines,andtheyareprintedasis.
One-liner2.2(page11)showsanotherwaytomatchnon-emptylinesthroughthe\Sregularexpression:
perl -pe '$_ = ++$x." $_" if /\S/'
Sayafilecontainsfourlines,twoofwhichareempty:
line1
line4
Runningthisone-linernumbersonlylinesoneandfour:
1 line1
2 line4
3.3Numberandprintonlynon-emptylinesinafile(dropemptylines)
perl -ne 'print ++$x." $_" if /./'
Thisone-linerusesthe-nprogramargument,whichplacesthelineinthe$_variableandthenexecutestheprogramspecifiedby-e.Unlike-p,-ndoesnotprintthelineafterexecutingthecodein-e,soyouhavetocallprintexplicitlytoprintthecontentsofthe$_variable.
Theone-linercallsprintonlyonlineswithatleastonecharacter,andasinthepreviousone-liner,itincrementsthelinenumberinthevariable$xbyoneforeachnon-emptyline.Theemptylinesareignoredandneverprinted.
Sayafilecontainsthesamefourlinesasinone-liner3.2:
line1
line4
Runningthisone-linerdropstheemptylinesandnumberslinesoneandfour:
1 line1
2 line4
3.4Numberalllinesbutprintlinenumbersonlyfornon-emptylines
perl -pe '$_ = "$. $_" if /./'
Thisone-linerissimilartoone-liner3.2.Here,youmodifythe$_variablethatholdstheentirelineonlyifthelinehasatleastonecharacter.Allotheremptylinesareprintedasis,withoutlinenumbers.
Sayafilecontainsfourlines:
line1
line4
Runningthisone-linernumbersallthelinesbutprintsthelinenumbersonlyforlinesoneandfour:
1 line1
4 line4
3.5Numberonlylinesthatmatchapattern;printothersunmodified
perl -pe '$_ = ++$x." $_" if /regex/'
Here,again,youusean“actionifcondition”statement,andagaintheconditionisapattern(aregularexpression):/regex/.Theactionisthesameasinone-liner3.2.
Sayafilecontainstheselines:
record foo
bar baz
record qux
andyouwanttonumberthelinesthatcontainthewordrecord.Youcanreplace/regex/intheone-linerwith/record/:
perl -pe '$_ = ++$x." $_" if /record/'
Whenyourunthisone-liner,itgivesyouthefollowingoutput:
1 record foo
bar baz
2 record qux
3.6Numberandprintonlylinesthatmatchapattern
perl -ne 'print ++$x." $_" if /regex/'
Thisone-linerisalmostexactlylikeone-liner3.3,exceptitonlynumbersandprintslinesthatmatch/regex/.Itdoesn’tprintnonmatchinglines.
Forexample,afilecontainsthesamelinesasinone-liner3.5:
record foo
bar baz
bar baz
record qux
Andlet’ssayyouwanttonumberandprintonlythelinesthatcontainthewordrecord.Inthiscase,changing/regex/to/record/andrunningtheone-linergivesyouthisresult:
1 record foo
2 record qux
3.7Numberalllinesbutprintlinenumbersonlyforlinesthatmatchapattern
perl -pe '$_ = "$. $_" if /regex/'
Thisone-linerissimilartoone-liners3.4and3.6.Here,thelinenumberisprependedtothelineifthelinematchesa/regex/;otherwise,it’ssimplyprintedwithoutalinenumber.
Replacing/regex/with/record/andrunningthisone-lineronthesameexamplefileshowninone-liner3.6givesyouthisoutput:
1 record foo
bar baz
3 record qux
3.8Numberalllinesinafileusingacustomformat
perl -ne 'printf "%-5d %s", $., $_'
Thisone-linerusesprintftoprintthelinenumbertogetherwiththelinecontents.printfdoesformattedprinting.Youspecifytheformatandsenditthedatatoprint,anditformatsandprintsthedataaccordingly.Here,theformatforthelinenumbersis%-5d,whichalignsthelinenumbersfivepositionstotheleft.
Here’sanexample.Saytheinputtothisone-lineris
hello world
bye world
Thentheoutputis
1 hello world
2 bye world
Otherformatstringsinclude%5d,whichalignsthelinenumbersfivepositionstotheright,and%05d,whichzero-fillsandright-justifiesthelinenumbers.Here’stheoutputyougetwiththe%5dformatstringforlinenumbers:
1 hello world
2 bye world
Andthisiswhatyougetwiththe%05dformatstring:
00001 hello world
00002 bye world
Tolearnmoreaboutthevariousformatsthatareavailable,runperldoc -fsprintfatthecommandline.
3.9Printthetotalnumberoflinesinafile(emulatewc-l)
perl -lne 'END { print $. }'
Thisone-linerusestheENDblockthatPerltookasafeaturefromtheAwklanguage.TheENDblockisexecutedoncethePerlprogramhasexecuted.Here,thePerlprogramisthehiddenloopovertheinputcreatedbythe-nargument.Onceitloopsovertheinput,thespecialvariable$.containsthenumberoflinesintheinput,andtheENDblockprintsthisvariable.The-lparametersetstheoutputrecordseparatorforprinttoanewline,soyoudon’thavetoprintthenewlineyourself,likethis:print "$.\n".
Youcandothesamethingwiththisone-liner:
perl -le 'print $n = () = <>'
Thisone-lineriseasytograspifyouunderstandPerlcontextswell.The() = <>parttellsPerltoevaluatethe<>operator(thediamondoperator)inthelistcontext,whichmakesthediamondoperatorreadthewholefileasalistoflines.Next,youassignthislistto$n.Because$nisscalar,thislistassignmentisevaluatedinthescalarcontext.
What’sreallyhappeninghereisthe=operatorisright-associative,meaningthe=ontherightisdonefirstandthe=ontheleftisdonesecond:
perl -le 'print $n = (() = <>)'
Evaluatingalistassignmentinthescalarcontextreturnsthenumberofelementsinthelist;thus,the$n = () = <>constructionisequaltothenumberoflinesintheinput,thatis,thenumberoflinesinthefile.Theprintstatementprintsthisnumber.The-largumentensuresanewlineisaddedafterprintingthisnumber.
Youcanalsodropthevariable$nfromthisone-linerandforcethescalarcontextthroughthescalaroperator:
perl -le 'print scalar(() = <>)'
Here,insteadofevaluatingalistassignmentinthescalarcontextbyassigningitagaintoanotherscalar,yousimplyevaluatethelistassignmentinthescalarcontextusingthescalaroperator.
Andnowforamoreobviousversion:
perl -le 'print scalar(@foo = <>)'
Here,insteadofusinganemptylist()toforcethelistcontexton<>,youusethevariable@footoachievethesameeffect.
Andhere’sanotherwaytodoit:
perl -ne '}{print $.'
perl -ne '}{print $.'
Thisone-linerusestheso-calledeskimooperator}{(actuallyacleverconstruct)inconjunctionwiththe-ncommand-lineargument.AsIexplainedearlier,the-nargumentforcesPerltoassumeawhile(<>) { }looparoundtheprogram.TheeskimooperatorforcesPerltoescapetheloop,andtheone-linerexpandsto
while (<>) {
}{ # eskimo operator here
print $.;
}
Asyoucansee,thisprogramjustloopsoveralltheinput,andonceit’sfinished,itprintsthe$.,whichisthenumberoflinesintheinput.Itbecomesevenmoreobviousifyouchangetheformattingalittle:
while (<>) {}
{
print $.;
}
Asyoucansee,thisisjustanemptyloopthatloopsoveralltheinput,followedbytheprintstatementwrappedincurlybrackets.
3.10Printthenumberofnon-emptylinesinafile
perl -le 'print scalar(grep { /./ } <>)'
Thisone-linerusesPerl’sgrepfunction,whichissimilartothegrepUNIXcommand.Givenalistofvalues,grep { condition } listreturnsonlythosevaluesinthelistthatmaketheconditiontrue.Inthiscase,theconditionisaregularexpressionthatmatchesatleastonecharacter,sotheinputisfilteredandgrep{ /./ }returnsallnon-emptylines.Togetthenumberoflines,youevaluategrepinthescalarcontextandprinttheresult.
SomePerlprogrammersliketocreatetheshortestPerlprogramthatdoessomeparticulartask—anexercisecalledPerlgolfing.Agolfer’sversionofthisone-
linerwouldreplacescalar()with~~(doublebitwisenegate)anddropthespaces,shorteningitlikethis:
perl -le 'print ~~grep{/./}<>'
Thisdoublebitwisenegatetrickiseffectivelyasynonymforscalarbecausethebitwisenegationworksonscalarvalues,sogrepisevaluatedinthescalarcontext.
Youcanmakethisevenshorterbydroppingthespaceafterprintandgettingridofthecurlybrackets:
perl -le 'print~~grep/./,<>'
IfyouhavePerl5.10orlater,youcanalsousethe-Ecommand-lineswitchandthesayoperator:
perl -lE 'say~~grep/./,<>'
Atruegolfer’smasterpiece!
3.11Printthenumberofemptylinesinafile
perl -lne '$x++ if /^$/; END { print $x+0 }'
Here,youusethevariable$xtocountthenumberofemptylinesencountered.Onceyou’veloopedoverallthelines,youprintthevalueof$xintheENDblock.Youusethe$x+0constructiontoensurethat0isoutputifnolinesareempty.(Otherwise$xisnevercreatedandisundefined.Adding+0totheundefinedvalueproduces0.)Analternativeto$x+0istheintoperator:
perl -lne '$x++ if /^$/; END { print int $x }'
Youcouldalsomodifythepreviousone-linerbydoingthis:
perl -le 'print scalar(grep { /^$/ } <>)'
Orwriteitwith~~:
perl -le 'print ~~grep{ /^$/ } <>'
The~~doesbitwisenegationtwice,whichmakesgrepexecuteinthescalarcontextandreturnthenumberofemptylines.
Theselasttwoversionsarenotaseffectiveastheone-linerwiththeENDblockbecausetheyreadthewholefileintomemory,whereastheone-linerwiththeENDblockdoesitlinebylineand,therefore,keepsonlyonelineofinputinmemory.
3.12Printthenumberoflinesinafilethatmatchapattern(emulategrep-c)
perl -lne '$x++ if /regex/; END { print $x+0 }'
Thisone-linerisbasicallythesameas3.11,exceptitincrementsthelinecounter$xbyonewhenalinematchestheregularexpression/regex/.The$x+0trickmakessure0isprintedwhennolinesmatch/regex/.(Seeone-liner3.11foramoredetailedexplanationofthe$x+0trick.)
3.13Numberwordsacrossalllines
perl -pe 's/(\w+)/++$i.".$1"/ge'
Thisone-linerusesthe/eflag,whichmakesPerlevaluatethereplacepartofthes/regex/replace/expressionascode!
Thecodehereis++$i.".$1",whichmeans“incrementvariable$ibyoneandthenadditinfrontofthestring".$1"(thatis,adotfollowedbythecontentsofthematchedgroup$1).”Thematchedgrouphereiseachword:(\w+).
Inonesentence,thisone-linermatchesaword(\w+),putsitin$1,andthenexecutesthe++$i.".$1"codethatnumbersthewordglobally(/gflag).There
—allwordsarenumbered.
Forexample,ifyouhaveafilewiththefollowingthreelines:
just another
perl hacker
hacking perl code
runningthisone-linernumberseachwordinthefileandproducesthefollowingoutput:
1.just 2.another
3.perl 4.hacker
5.hacking 6.perl 7.code
3.14Numberwordsoneachindividualline
perl -pe '$i=0; s/(\w+)/++$i.".$1"/ge'
Thisissimilartoone-liner3.13,exceptthatyouresetthe$ivariableto0oneachline.Here’stheresultofrunningthisone-linerontheexamplefromone-liner3.13:
1.just 2.another
1.perl 2.hacker
1.hacking 2.perl 3.code
Asyoucansee,ineachlinethewordsarenumberedindependentlyofotherlines.
3.15Replaceallwordswiththeirnumericpositions
perl -pe 's/(\w+)/++$i/ge'
Thisone-linerisalmostthesameasone-liner3.13.Here,yousimplyreplaceeachwordwithitsnumericposition,whichiskeptinthevariable$i.For
example,ifyourunthisone-lineronthefilefromone-liners3.13and3.14,itreplacesthewordsinthefilewiththeirnumericpositionstoproducethisoutput:
1 2
3 4
5 6 7
Fun!
Chapter4.Calculations
Inthischapter,we’lllookatvariousone-linersforperformingcalculations,suchasfindingminimumandmaximumelements,counting,shufflingandpermutingwords,andcalculatingdatesandnumbers.You’llalsolearnaboutthe-a,-M,and-Fcommand-linearguments,the$,specialvariable,andthe@{[ ... ]}constructionthatletsyouruncodeinsidedoublequotes.
4.1Checkifanumberisaprime
perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'
Thisone-linerusesaningeniousregularexpressionbyAbigailtodetectwhetheragivennumberisaprime.(Don’ttakethisregularexpressiontooseriously;I’veincludeditforitsartisticvalue.Forseriouspurposes,usetheMath::PrimalitymodulefromCPANtoseewhetheranumberisprime.)
Here’showthisingeniousone-linerworks:First,thenumberisconvertedintoitsunaryrepresentationby(1x$_).Forexample,5isconvertedinto1x5,whichis11111(1repeated5times).Next,theunarynumberistestedagainsttheregularexpression.Ifitdoesn’tmatch,thenumberisaprime;otherwiseit’sacomposite.The!~operatoristheoppositeofthe=~operatorandistrueiftheregularexpressiondoesn’tmatch.
Theregularexpressionconsistsoftwoparts:Thefirstpart,^1?$,matches1andtheemptystring.Theemptystringand1areclearlynotprimenumbers,sothispartoftheregularexpressiondiscardsthem.
Thesecondpart,^(11+?)\1+$,determineswhethertwoormore1srepeatedlymakeupthewholenumber.Ifso,theregularexpressionmatches,whichmeansthenumberisacomposite.Ifnot,it’saprime.
Nowconsiderhowthesecondpartoftheregularexpressionwouldactonthe
number5.Thenumber5inunaryis11111,sothe(11+?)matchesthefirsttwo1s,theback-reference\1becomes11,andthewholeregularexpressionnowbecomes^11(11)+$.Becauseitcan’tmatchfive1s,itfails.Next,itattemptstomatchthefirstthree1s.Theback-referencebecomes111,andthewholeregularexpressionbecomes^111(111)+$,whichdoesn’tmatch.Theprocessrepeatsfor1111and11111,whichalsodon’tmatch,andasaresulttheentireregularexpressiondoesn’tmatchandthenumberisaprime.
Whataboutthenumber4?Thenumber4is1111inunary.The(11+?)matchesthefirsttwo1s.Theback-reference\1becomes11,andtheregularexpressionbecomes^11(11)+$,whichmatchestheoriginalstringandconfirmsthatthenumberisnotprime.
4.2Printthesumofallfieldsoneachline
perl -MList::Util=sum -alne 'print sum @F'
Thisone-linerturnsonfieldauto-splittingwiththe-acommand-lineoptionandimportsthesumfunctionfromtheList::Utilmodulewith-Mlist::Util=sum.(List::UtilispartofthePerlcore,soyoudon’tneedinstallit.)Auto-splittinghappensonwhitespacecharactersbydefault,[email protected],theline1 4 8wouldbesplitoneachspacesothat@Fwouldbecome(1, 4, 8).Thesum @Fstatementsumstheelementsinthe@Farray,givingyou13.
The-Mmodule=argoptionimportsargfrommodule.It’sthesameaswriting
use module qw(arg);
Thisone-linerisequivalentto
use List::Util qw(sum);
while (<>) {
@F = split(' ');
print sum @F, "\n";
}
Youcanchangeauto-splitting’sdefaultbehaviorbyspecifyinganargumenttothe-Fcommand-lineswitch.Sayyouhavethefollowingline:
1:2:3:4:5:6:7:8:9:10
Andyouwishtofindthesumofallthesenumbers.Youcansimplyspecify:asanargumenttothe-Fswitch,likethis:
perl -MList::Util=sum -F: -alne 'print sum @F'
Thissplitsthelineonthecoloncharacterandsumsallthenumbers.Theoutputis55becausethat’sthesumofthenumbers1through10.
4.3Printthesumofallfieldsonalllines
perl -MList::Util=sum -alne 'push @S,@F; END { print sum @S }'
Thisone-linerkeepspushingthesplitfieldsin@[email protected],theEND { }blockisexecutedanditoutputsthesumofallitemsin@F.Thissumsallfieldsoveralllines.
Noticehowpushingthe@Farraytothe@Sarrayactuallyappendselementstoit.Thisdiffersfrommanyotherlanguages,wherepushingarray1toarray2wouldputarray1intoarray2,ratherthanappendingtheelementsofarray1ontoarray2.Perlperformslistflatteningbydesign.
Unfortunately,summingallfieldsonalllinesusingthissolutioncreatesamassive@Sarray.Abettersolutionistokeeponlytherunningsum,likethis:
perl -MList::Util=sum -alne '$s += sum @F; END { print $s }'
Here,eachlineissplitinto@Fandthevaluesaresummedandstoredintherunningsumvariable$s.Onceallinputhasbeenprocessed,theone-linerprintsthevalueof$s.
4.4Shuffleallfieldsoneachline
4.4Shuffleallfieldsoneachline
perl -MList::Util=shuffle -alne 'print "@{[shuffle @F]}"'
Thetrickiestpartofthisone-lineristhe@{[shuffle @F]}construction.Thisconstructionallowsyoutoexecutethecodeinsidethequotationmarks.Normallytextandvariablesareplacedinsidequotationmarks,butwiththe@{[... ]}constructionyoucanruncode,too.
Inthisone-liner,thecodetoexecuteinsideofthequotationmarksisshuffle@F,whichshufflesthefieldsandreturnstheshuffledlist.The[shuffle @F]createsanarrayreferencecontainingtheshuffledfields,andthe@{ ... }dereferencesit.Yousimplycreateareferenceandimmediatelydereferenceit.Thisallowsyoutorunthecodeinsidethequotationmarks.
Let’slookatseveralexamplestounderstandwhyIchosetorunthecodeinsidethequotationmarks.IfIhadwrittenprint shuffle @F,thefieldsonthelinewouldbeconcatenated.Comparetheoutputofthisone-liner:
$ echo a b c d | perl -MList::Util=shuffle -alne 'print "@{[shuffle @F]}"'
b c d a
tothis:
$ echo a b c d | perl -MList::Util=shuffle -alne 'print shuffle @F'
bcda
Inthefirstexample,thearrayofshuffledfields(insidethedoublequotationmarks)isinterpolated,andthearray’selementsareseparatedbyaspace,sotheoutputisb c d a.Inthesecondexample,interpolationdoesn’thappen,andPerlsimplydumpsoutelementbyelementwithoutseparatingthem,andtheoutputisbcda.
Youcanusethe$,specialvariabletochangetheseparatorbetweenarrayelementswhenthey’reprinted.Forexample,here’swhathappenswhenIchangetheseparatortoacolon:
$ echo a b c d | perl -MList::Util=shuffle -alne '$,=":"; print shuffle @F'
b:c:d:a
Youcanalsousethejoinfunctiontojointheelementsof@Fwithaspace:
perl -MList::Util=shuffle -alne 'print join " ", shuffle @F'
Here,thejoinfunctionjoinstheelementsofanarrayusingthegivenseparator,butthe@{[ ... ]}constructionisthecleanestwaytodoit.
4.5Findthenumericallysmallestelement(minimumelement)oneachline
perl -MList::Util=min -alne 'print min @F'
Thisone-linerissomewhatsimilartothepreviousones.ItusestheminfunctionfromList::Util.Oncethelinehasbeenautomaticallysplitby-aandtheelementsareinthe@Farray,theminfunctionfindsthenumericallysmallestelement,whichitprints.
Forexample,ifyouhaveafilethatcontainstheselines:
-8 9 10 5
7 0 9 3
5 -25 9 999
Runningthisone-linerproducesthefollowingoutput:
-8
0
-25
Thesmallestnumberonthefirstlineis-8;onthesecondline,thesmallestnumberis0;andonthethirdline,-25.
4.6Findthenumericallysmallestelement(minimumelement)overalllines
perl -MList::Util=min -alne '@M = (@M, @F); END { print min @M }'
perl -MList::Util=min -alne '@M = (@M, @F); END { print min @M }'
Thisone-linercombinesone-liners4.3and4.5.The@M = (@M, @F)constructisthesameaspush @M, @F.Itappendsthecontentsof@Ftothe@Marray.
Thisone-linerstoresalldatainmemory,andifyourunitonareallyhugefile,Perlwillrunoutofmemory.Yourbestbetistofindthesmallestelementoneverylineandcomparethatelementwiththesmallestelementonthepreviousline.Iftheelementonthecurrentlineislessthanthepreviousone,it’sthesmallestelementsofar.Oncealllineshavebeenprocessed,youcanjustprintthesmallestelementfoundthroughtheENDblock:
perl -MList::Util=min -alne '
$min = min @F;
$rmin = $min unless defined $rmin && $min > $rmin;
END { print $rmin }
'
Here,youfirstfindtheminimumelementonthecurrentlineandstoreitin$min.Thenyouchecktoseeifthesmallestelementonthecurrentlineisthesmallestelementsofar.Ifso,assignitto$rmin.Onceyou’veloopedoverthewholeinput,theENDblockexecutesandyouprintthe$rmin.
Sayyourfilecontainstheselines:
-8 9 10 5
7 0 9 3
5 -25 9 999
Runningthisone-lineroutputs-25becausethat’sthesmallestnumberinthefile.
Ifyou’reusingPerl5.10orlater,youcandothesamethingwiththisone-liner:
perl -MList::Util=min -alne '$min = min($min // (), @F); END { print $min }'
Thisone-linerusesthe//operator,whichisnewtoPerl5.10.ThisoperatorissimilartothelogicalORoperator(||),exceptthatitteststheleftside’sdefinednessratherthanthetruth.Whatthatmeansisittestswhethertheleftsideisdefinedratherthanwhetheritistrueorfalse.Inthisone-liner,theexpression$min // ()returns$minif$minhasbeendefined,orelseitreturnsanempty
list().The//operatorsavesyoufromhavingtousedefinedtotestdefinedness.
Considerwhathappenswhenthisone-linerisrunonthepreviousfile.First,Perlreadstheline-8 9 10 5,splitsit,[email protected]@Farrayisnow(-8, 9, 10, 5).Next,itexecutes$min = min ($min // (),@F).Because$minhasn’tbeendefined,$min // ()evaluatesto(),sothewholeexpressionbecomes$min = min ((), (-8, 9, 10, 5)).
Perldoeslistflatteningbydesign,soafterflatteningtheargumentstotheminfunction,theexpressionbecomes$min = min(-8, 9, 10, 5).Thisdefines$min,settingitto-8.Perlproceedstothenextline,whereitsets@Fto(7, 0,9, 3)andagainevaluates$min = min($min // (), @F).Because$minhasnowbeendefined,$min // ()evaluatesto$minandtheexpressionbecomes$min = min(-8, 7, 0, 9, 3).Atthispoint,-8isstillthesmallestelement,so$minremains-8.Finally,Perlreadsinthelastline,andafterevaluating$min =min(-8, 5, -25, 9, 999),itfindsthat-25isthesmallestelementinthefile.
4.7Findthenumericallylargestelement(maximumelement)oneachline
perl -MList::Util=max -alne 'print max @F'
Thisworksthesameasone-liner4.5,exceptthatyoureplaceminwithmax.
4.8Findthenumericallylargestelement(maximumelement)overalllines
perl -MList::Util=max -alne '@M = (@M, @F); END { print max @M }'
Thisone-linerissimilartoone-liners4.6and4.7.Inthisone-liner,eachlineisauto-splitandputinthe@Farray,andthenthisarrayismergedwiththe@Marray.Whentheinputhasbeenprocessed,theENDblockexecutesandthemaximumelementisprinted.
Here’sanotherwaytofindthemaximumelement,keepingjusttherunningmaximumelementinsteadofallelementsinmemory:
perl -MList::Util=max -alne '
$max = max @F;
$rmax = $max unless defined $rmax && $max < $rmax;
END { print $rmax }
'
Ifyou’reusingPerl5.10orlater,youcanusethe//operatortoshortenthisone-liner:
perl -MList::Util=max -alne '$max = max($max // (), @F); END { print $max }'
Thisisthesameasone-liner4.6,exceptyoureplaceminwithmax.
4.9Replaceeachfieldwithitsabsolutevalue
perl -alne 'print "@{[map { abs } @F]}"'
Thisone-linerfirstauto-splitsthelineusingthe-aoption.Thesplitfieldsendupinthe@Fvariable.Next,itcallstheabsolutevaluefunctionabsoneachfieldwiththehelpofthemapfunction.Essentially,themapfunctionappliesagivenfunctiontoeachelementofthelistandreturnsanewlistthatcontainstheresultsofapplyingthefunction.Forexample,ifthelist@Fis(-4, 2, 0),mappingabsoveritproducesthelist(4, 2, 0).Finally,thisone-linerprintsthenewlistofpositivevalues.
The@{[ ... ]}construct,introducedinone-liner4.4,allowsyoutoexecutethecodeinsidethequotationmarks.
4.10Printthetotalnumberoffieldsoneachline
perl -alne 'print scalar @F'
Thisone-linerforcestheevaluationof@Finthescalarcontext,whichinPerl
means“thenumberofelementsin@F.”Asaresult,itprintsthenumberofelementsoneachline.
Forexample,ifyourfilecontainsthefollowinglines:
foo bar baz
foo bar
baz
Runningthisone-linerproducesthefollowingoutput:
3
2
1
Thefirstlinehasthreefields,thesecondlinehastwofields,andthelastlinehasonefield.
4.11Printthetotalnumberoffieldsoneachline,followedbytheline
perl -alne 'print scalar @F, " $_"'
Thisone-lineristhesameasone-liner4.10,withtheadditionof$_attheend,whichprintsthewholeline.(Rememberthat-nputseachlineinthe$_variable.)
Let’srunthisone-lineronthesameexamplefilethatIusedinone-liner4.10:
foo bar baz
foo bar
baz
Runningtheone-linerproducesthefollowingoutput:
3 foo bar baz
2 foo bar
1 baz
4.12Printthetotalnumberoffieldsonalllines
perl -alne '$t += @F; END { print $t }'
Here,theone-linerkeepsaddingthenumberoffieldsoneachlinetovariable$tuntilalllineshavebeenprocessed.Next,itprintstheresult,whichcontainsthenumberofwordsonalllines.Noticethatyouaddthe@Farraytothescalarvariable$t.Because$tisscalar,the@Farrayisevaluatedinthescalarcontextandreturnsthenumberofelementsitcontains.
Runningthisone-lineronthefollowingfile:
foo bar baz
foo bar
baz
producesthenumber6asoutputbecausethefilecontainsatotalofsixwords.
4.13Printthetotalnumberoffieldsthatmatchapattern
perl -alne 'map { /regex/ && $t++ } @F; END { print $t || 0 }'
Thisone-linerusesmaptoapplyanoperationtoeachelementinthe@Farray.Inthisexample,theoperationcheckstoseeifeachelementmatches/regex/,andifitdoes,itincrementsthe$tvariable.Itthenprintsthe$tvariable,whichcontainsthenumberoffieldsthatmatchthe/regex/pattern.The$t || 0constructisnecessarybecauseifnofieldsmatch,$twouldn’texist,soyoumustprovideadefaultvalue.Insteadof0,youcanprovideanyotherdefaultvalue,evenastring!
Loopingwouldbeabetterapproach:
perl -alne '$t += /regex/ for @F; END { print $t }'
Here,eachelementin@Fistestedagainst/regex/.Ifitmatches,/regex/
returnstrue;otherwiseitreturnsfalse.Whenusednumerically,trueconvertsto1andfalseconvertsto0,so$t += /regex/addseither1or0tothe$tvariable.Asaresult,thenumberofmatchesiscountedin$t.YoudonotneedadefaultvaluewhenprintingtheresultintheENDblockbecausethe+=operatorisrunregardlessofwhetherthefieldmatches.Youwillalwaysgetavalue,andsometimesthatvaluewillbe0.
Anotherwaytodothisistousegrepinthescalarcontext:
perl -alne '$t += grep /regex/, @F; END { print $t }'
Here,grepreturnsthenumberofmatchesbecauseit’sevaluatedinthescalarcontext.Inthelistcontext,grepreturnsallmatchingelements,butinthescalarcontext,itreturnsthenumberofmatchingelements.Thisnumberisaccumulatedin$tandprintedintheENDblock.Inthiscase,youdon’tneedtoprovideadefaultvaluefor$tbecausegrepreturns0inthosesituations.
4.14Printthetotalnumberoflinesthatmatchapattern
perl -lne '/regex/ && $t++; END { print $t || 0 }'
Here,/regex/evaluatestotrueifthecurrentlineofinputmatchesthisregularexpression.Writing/regex/ && $t++isthesameaswritingif ($_ =~/regex/) { $t++ },whichincrementsthe$tvariableifthelinematchesthespecifiedpattern.IntheENDblock,the$tvariablecontainsthetotalnumberofpatternmatchesandisprinted;butifnolinesmatch,$tisonceagainundefined,soyoumustprintadefaultvalue.
4.15Printthenumberπ
perl -Mbignum=bpi -le 'print bpi(21)'
Thebignumpackageexportsthebpifunctionthatcalculatestheπconstanttothedesiredaccuracy.Thisone-linerprintsπto20decimalplaces.(Noticethatyouneedtospecifyn+1toprintittoanaccuracyofn.)
Thebignumlibraryalsoexportstheconstantπ,precomputedto39decimalplaces:
perl -Mbignum=PI -le 'print PI'
4.16Printthenumbere
perl -Mbignum=bexp -le 'print bexp(1,21)'
Thebignumlibraryexportsthebexpfunction,whichtakestwoarguments:thepowertoraiseeto,andthedesiredaccuracy.Thisone-linerprintstheconstanteto20decimalplaces.
Forexample,youcouldprintthevalueofe2to30decimalplaces:
perl -Mbignum=bexp -le 'print bexp(2,31)'
Aswithπ,bignumalsoexportstheconstanteprecomputedto39decimalplaces:
perl -Mbignum=e -le 'print e'
4.17PrintUNIXtime(secondssinceJanuary1,1970,00:00:00UTC)
perl -le 'print time'
Thebuilt-intimefunctionreturnssecondssincetheepoch.Thisone-linersimplyprintsthetime.
4.18PrintGreenwichMeanTimeandlocalcomputertime
computertime
perl -le 'print scalar gmtime'
Thegmtimefunctionisabuilt-inPerlfunction.Whenusedinthescalarcontext,itreturnsthetimelocalizedtoGreenwichMeanTime(GMT).
Thebuilt-inlocaltimefunctionactslikegmtime,exceptitreturnsthecomputer’slocaltimewhenit’susedinthescalarcontext:
perl -le 'print scalar localtime'
Inthelistcontext,bothgmtimeandlocaltimereturnanine-elementlist(knownasstruct tmtoUNIXprogrammers)withthefollowingelements:
($second, [0]
$minute, [1]
$hour, [2]
$month_day, [3]
$month, [4]
$year, [5]
$week_day, [6]
$year_day, [7]
$is_daylight_saving [8]
)
Youcanslicethislist(thatis,extractelementsfromit)orprintindividualelementsifyouneedjustsomepartoftheinformationitcontains.Forexample,toprintH:M:S,slicetheelements2,1,and0fromlocaltime,likethis:
perl -le 'print join ":", (localtime)[2,1,0]'
Tosliceelementsindividually,specifyalistofelementstoextract,forinstance[2,1,0].Orslicethemasarange:
perl -le 'print join ":", (localtime)[2..6]'
Thisone-linerprintsthehour,date,month,year,anddayoftheweek.
Youcanalsousenegativeindexestoselectelementsfromtheoppositeendofalist:
list:
perl -le 'print join ":", (localtime)[-2, -3]'
Thisone-linerprintselements7and6,whicharethedayoftheyear(forexample,the200thday)andoftheweek(forexample,the4thday),respectively.
4.19Printyesterday’sdate
perl -MPOSIX -le '
@now = localtime;
$now[3] -= 1;
print scalar localtime mktime @now
'
Rememberthatlocaltimereturnsanine-itemlist(seeone-liner4.18)ofvariousdateelements.Thefourthelementinthelististhecurrentmonth’sday.Ifyousubtract1fromthiselement,yougetyesterday.
ThemktimefunctionconstructstheUNIXepochtimefromthismodifiednine-elementlist,andthescalar localtimeconstructprintsthenewdate,whichisyesterday.Thisone-lineralsoworksinedgecases,suchaswhenthecurrentdayisthefirstdayofthemonth.YouneedthePOSIXpackagebecauseitexportsthemktimefunction.
Forexample,ifit’sMonMay2005:49:55rightnow,runningthisone-linerprintsSunMay1905:49:55.
4.20Printthedate14months,9days,and7secondsago
perl -MPOSIX -le '
@now = localtime;
$now[0] -= 7;
$now[3] -= 9;
$now[4] -= 14;
print scalar localtime mktime @now
'
'
Thisone-linermodifiesthefirst,fourth,[email protected],thefourthisdays,andthefifthismonths.ThemktimecommandgeneratestheUNIXtimefromthisnewstructure,andlocaltime,whichisevaluatedinthescalarcontext,printsthedate14months,9days,and7secondsago.
4.21Calculatethefactorial
perl -MMath::BigInt -le 'print Math::BigInt->new(5)->bfac()'
Thisone-linerusesthebfac()functionfromtheMath::BigIntmoduleinthePerlcore.(Inotherwords,youdon’tneedtoinstallit.)TheMath::BigInt->new(5)constructioncreatesanewMath::BigIntobjectwithavalueof5,afterwhichthebfac()methodiscalledonthenewlycreatedobjecttocalculatethefactorialof5.Change5toanynumberyouwishtofinditsfactorial.
Anotherwaytocalculateafactorialistomultiplythenumbersfrom1tontogether:
perl -le '$f = 1; $f *= $_ for 1..5; print $f'
Here,Iset$fto1andthenloopfrom1to5andmultiply$fbyeachvalue.Theresultis120(1*2*3*4*5),thefactorialof5.
4.22Calculatethegreatestcommondivisor
perl -MMath::BigInt=bgcd -le 'print bgcd(@list_of_numbers)'
Math::BigInthasseveralotherusefulmathfunctionsincludingbgcd,whichcalculatesthegreatestcommondivisor(gcd)ofalistofnumbers.Forexample,tofindthegreatestcommondivisorof(20, 60, 30),executetheone-linerlikethis:
perl -MMath::BigInt=bgcd -le 'print bgcd(20,60,30)'
perl -MMath::BigInt=bgcd -le 'print bgcd(20,60,30)'
Tocalculatethegcdfromafileoruser’sinput,usethe-acommand-lineargumentandpassthe@Farraytothebgcdfunction:
perl -MMath::BigInt=bgcd -anle 'print bgcd(@F)'
YoucouldalsouseEuclid’salgorithmtofindthegcdof$nand$m.Thisone-linerdoesjustthatandstorestheresultin$m:
perl -le '
$n = 20; $m = 35;
($m,$n) = ($n,$m%$n) while $n;
print $m
'
Euclid’salgorithmisoneoftheoldestalgorithmsforfindingthegcd.
4.23CalculatetheleastcommonmultipleTheleastcommonmultiple(lcm)function,blcm,isincludedinMath::BigInt.Usethisone-linertofindtheleastcommonmultipleof(35, 20, 8):
perl -MMath::BigInt=blcm -le 'print blcm(35,20,8)'
Tofindthelcmfromafilewithnumbers,usethe-acommand-lineswitchandthe@Farray:
perl -MMath::BigInt=blcm -anle 'print blcm(@F)'
Ifyouknowabitofnumbertheory,youmayrecallthatthereisaconnectionbetweenthegcdandthelcm.Giventwonumbers$nand$m,youknowthattheirlcmis$n*$m/gcd($n,$m).Thisone-liner,therefore,follows:
perl -le '
$a = $n = 20;
$b = $m = 35;
$b = $m = 35;
($m,$n) = ($n,$m%$n) while $n;
print $a*$b/$m
'
4.24Generate10randomnumbersbetween5and15(excluding15)
perl -le 'print join ",", map { int(rand(15-5))+5 } 1..10'
Thisone-linerprints10randomnumbersbetween5and15.Itmaylookcomplicated,butit’sactuallysimple.int(rand(15-5))isjustint(rand(10)),whichreturnsarandomintegerfrom0to9.Adding5toitmakesitreturnarandomintegerfrom5to14.Therange1..10makesitdraw10randomintegers.
Youcanalsowritethisone-linermoreverbosely:
perl -le '
$n=10;
$min=5;
$max=15;
$, = " ";
print map { int(rand($max-$min))+$min } 1..$n;
'
Here,allvariablesaremoreexplicit.Tomodifythisone-liner,changethevariables$n,$min,and$max.The$nvariablerepresentshowmanyrandomnumberstogenerate,and$min-$maxistherangeofnumbersforuseinthatgeneration.
The$,variableissettoaspacebecauseit’stheoutputfieldseparatorforprintandit’sundefbydefault.Ifyoudidn’tset$,toaspace,thenumberswouldbeprintedconcatenated.(Seeone-liner4.4onpage32foradiscussionof$,.)
4.25Generateallpermutationsofalist
perl -MAlgorithm::Permute -le '
$l = [1,2,3,4,5];
$l = [1,2,3,4,5];
$p = Algorithm::Permute->new($l);
print "@r" while @r = $p->next
'
Thisone-linerusestheobject-orientedinterfaceofthemoduleAlgorithm::Permutetofindallpermutationsofalist,thatis,allwaystorearrangeitems.TheconstructorofAlgorithm::Permutetakesanarrayreferenceofelementstopermute.Inthisparticularone-liner,theelementsarethenumbers1, 2, 3, 4, 5.
Thenextmethodreturnsthenextpermutation.Callingitrepeatedlyiteratesoverallpermutations,andeachpermutationisputinthe@rarrayandthenprinted.(Beware:Theoutputlistgetslargereallyquickly.Therearen!(nfactorial)permutationsforalistofnelements.)
Anotherwaytoprintallpermutationsiswiththepermutesubroutine:
perl -MAlgorithm::Permute -le '
@l = (1,2,3,4,5);
Algorithm::Permute::permute { print "@l" } @l
'
Here’swhatyougetifyouchange@ltojustthreeelements(1, 2, 3)andrunit:
1 2 3
1 3 2
3 1 2
2 1 3
2 3 1
3 2 1
4.26Generatethepowerset
perl -MList::PowerSet=powerset -le '
@l = (1,2,3,4,5);
print "@$_" for @{powerset(@l)}
'
Thisone-linerusestheList::PowerSetmodulefromCPAN.Themoduleexportsthepowersetfunction,whichtakesalistofelementsandreturnsareferencetoanarraycontainingreferencestosubsetarrays.Youcaninstallthismodulebyrunningcpan List::PowerSetatthecommandline.
Intheforloop,[email protected],youdereferencethereturnvalueofpowerset,whichisareferencetoanarrayofsubsets,andthendereferenceeachindividualsubset@$_andprintit.
Thepowersetisthesetofallsubsets.Forasetofnelements,thereareexactly2n
subsetsinthepowerset.Here’sanexampleofthepowersetof(1, 2, 3):
1 2 3
2 3
1 3
3
1 2
2
1
4.27ConvertanIPaddresstoanunsignedinteger
perl -le '
$i=3;
$u += ($_<<8*$i--) for "127.0.0.1" =~ /(\d+)/g;
print $u
'
Thisone-linerconvertstheIPaddress127.0.0.1intoanunsignedintegerbyfirstdoingaglobalmatchof(\d+)ontheIPaddress.Performingaforloopoveraglobalmatchiteratesoverallthematches,whicharethefourpartsoftheIPaddress:127,0,0,1.
Next,thematchesaresummedinthe$uvariable.Thefirstbitisshifted8×3=24places,thesecondisshifted8×2=16places,andthethirdisshifted8places.Thelastissimplyaddedto$u.Theresultingintegerhappenstobe2130706433(averygeekynumber).
Herearesomemoreone-liners:
Herearesomemoreone-liners:
perl -le '
$ip="127.0.0.1";
$ip =~ s/(\d+)\.?/sprintf("%02x", $1)/ge;
print hex($ip)
'
Thisone-linerutilizesthefactthat127.0.0.1canbeeasilyconvertedtohex.Here,the$ipismatchedagainst(\d+),andeachIPpartistransformedintoahexnumberwithsprintf("%02x", $1)insidethesoperator.The/eflagofthesoperatormakesitevaluatethesubstitutionpartasaPerlexpression.Asaresult,127.0.0.1istransformedinto7f000001andtheninterpretedasahexadecimalnumberbyPerl’shexoperator,whichconvertsittoadecimalnumber.
Youcanalsouseunpack:
perl -le 'print unpack("N", 127.0.0.1)'
Thisone-linerisprobablyasshortaspossible.Itusesvstringliterals(versionstrings)toexpresstheIPaddress.Avstringformsastringliteralcomposedofcharacterswiththespecifiedordinalvalues.Thenewlyformedstringliteralisunpackedintoanumberfromastringinnetworkbyteorder(big-endianorder)andthenprinted.
IfyouhaveastringwithanIP(ratherthanavstring),youfirsthavetoconvertittobyteformwiththefunctioninet_aton:
perl -MSocket -le 'print unpack("N", inet_aton("127.0.0.1"))'
Here,inet_atonconvertsthestring127.0.0.1tothebyteform(equivalenttothepurevstring127.0.0.1)andthenunpackunpacksit,asinthepreviousone-liner.
4.28ConvertanunsignedintegertoanIPaddress
perl -MSocket -le 'print inet_ntoa(pack("N", 2130706433))'
Here,theinteger2130706433ispackedintoanumberinbig-endianbyteorderandthenpassedtotheinet_ntoafunctionthatconvertsanumberbacktoanIPaddress.(Noticethatinet_ntoaistheoppositeofinet_aton.)
Youcandothesamethinglikethis:
perl -le '
$ip = 2130706433;
print join ".", map { (($ip>>8*($_))&0xFF) } reverse 0..3
'
Here,the$ipisshifted24bitstotherightandthenbitwiseANDedwith0xFFtoproducethefirstpartoftheIP,whichis127.Next,it’sshifted16bitsandbitwiseANDedwith0xFF,producing0,andthenshifted8bitsandbitwiseANDedwith0xFF,producinganother0.Finally,thewholenumberisbitwiseANDedwith0xFF,producing1.
Theresultfrommap { ... }isalist(127, 0, 0, 1).Thatlistisnowjoinedbyadot"."toproducetheIPaddress127.0.0.1.
Youcanreplacejoinwiththespecialvariable$,,whichactsasavalueseparatorfortheprintstatement:
perl -le '
$ip = 2130706433;
$, = ".";
print map { (($ip>>8*($_))&0xFF) } reverse 0..3
'
Becausereverse 0..3isthesameas3,2,1,0,youcouldalsowrite:
perl -le '
$ip = 2130706433;
$, = ".";
print map { (($ip>>8*($_))&0xFF) } 3,2,1,0
'
Chapter5.WorkingWithArraysandStrings
Inthischapter,we’lllookatvariousone-linersforcreatingstringsandarrays,fordoingthingslikegeneratingpasswords,creatingstringsofcertainlength,findingthenumericvaluesofcharacters,andcreatingarraysofnumbers.You’llalsolearnabouttherangeoperator..,thexoperator,the$,specialvariable,andthe@ARGVarray.
5.1Generateandprintthealphabet
perl -le 'print a..z'
Thisone-linerprintsalllettersfromatozintheEnglishalphabetasabcdefghijklmnopqrstuvwxyz.Thelettersaregeneratedbytherangeoperator..,which,whenusedonstringsinthelistcontext(providedherebyprint),appliesthemagicalauto-incrementalgorithmthatadvancesthestringtothenextcharacter.Therefore,inthisone-liner,theauto-incrementalgorithmontherangea..zproducesalllettersfromatoz.
Ireallygolfedthisone-liner.IfIhadusedstrict,itwouldn’thaveworkedbecauseofthebarewordsaandz.Thisversionismorecorrectsemantically:
perl -le 'print ("a".."z")'
Rememberthattherangeoperator..producesalistofvalues.Ifyouwish,youcouldprintthevalueswithcommaseparationsbysettingthe$,specialvariable:
perl -le '$, = ","; print ("a".."z")'
The$,isthefieldseparator.It’soutputbyprintbetweeneachfield.Semantically,though,usingjointoseparatethelistofletterswithacommaismoreappealingbecauseitworksevenwhennotusingprintdirectly:
perl -le '$alphabet = join ",", ("a".."z"); print $alphabet'
Here,thelista..zisjoinedbyacommabeforeprinting,andtheoutputis
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
5.2Generateandprintallthestringsfrom“a”to“zz”
perl -le 'print join ",", ("a".."zz")'
Thisone-linerusestherangeoperator..again,butthistime,itdoesn’tstopatzasinthepreviousone-liner.Instead,itadvanceszbyonecharacter,producingaa.Thenitkeepsgoing,producingab,ac,andsoon,untilithitsaz.Atthatpoint,itadvancesthestringtoba,continueswithbb,bc,andsoon,untileventuallyitreacheszz.
Youcouldalsogenerateallstringsfromaatozzbydoingthis:
perl -le 'print join ",", "aa".."zz"'
Theoutputfromthisone-lineris
aa, ab, ..., az, ba, bb, ..., bz, ca, ..., zz
5.3Createahexlookuptable
@hex = (0..9, "a".."f")
Inthisone-liner,the@hexarrayisfilledwiththenumbers0,1,2,3,4,5,6,7,8,9andthelettersa,b,c,d,e,f.Youcouldusethisarraytoconvertanumber(in
variable$num)fromdecimaltohexwiththefollowingbaseconversionformula.(Thisisn’taone-liner;Iincludeittoillustratehowtousethe@hexlookuparray.)
perl -le '
$num = 255;
@hex = (0..9, "a".."f");
while ($num) {
$s = $hex[($num % 16)].$s;
$num = int $num/16;
}
print $s
'
Butsurely,convertinganumbertohexismucheasierifIuseprintf(orsprintf)withthe%xformatspecifier.
perl -le 'printf("%x", 255)'
Toconvertthenumberbackfromhextodec,usethehexoperator:
perl -le '$num = "ff"; print hex $num'
Thehexoperatortakesahexstring(beginningwithorwithout0x)andconvertsittodecimal.
5.4Generatearandomeight-characterpassword
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
Here,themapoperatorexecutesthecode("a".."z")[rand 26]eighttimesbecauseititeratesovertherange1..8.Ineachiteration,thecodechoosesarandomletterfromthealphabet.Whenmaphasfinishediterating,itreturnsthegeneratedlistofcharacters,andprintprintsit,therebyconcatenatingallthecharacters.
Toalsoincludenumbersinthepassword,add0..9tothelistofcharactersto
choosefromandchange26to36becauseyounowhave36possiblecharacters:
perl -le 'print map { ("a".."z", 0..9)[rand 36] } 1..8'
Ifyouneedalongerpassword,change1..8to1..20togenerateonethat’s20characterslong.
5.5Createastringofspecificlength
perl -le 'print "a"x50'
Thisone-linercreatesastringof50lettersaandprintsit.Operatorxistherepetitionoperator.Here,theletteraisrepeated50timesbyx50.Thisone-linerishandywhenyouneedtogenerateaspecificamountofdatafordebuggingorothertasks.Forexample,ifyouneed1KBofdata,justdothis:
perl -e 'print "a"x1024'
Iremovedthe-largumentbecauseitwouldhaveoutputanadditionalnewlinesymbol,producing1025bytesofdata.
Whenyouusetherepetitionoperatorinthelistcontext,withalistasitsfirstoperand,youcreatealistwiththegivenelementsrepeated,likethis:
perl -le '@list = (1,2)x20; print "@list"'
Thisone-linercreatesalistof20repetitionsof(1, 2)thatlookslike(1, 2,1, 2, 1, 2, ...).(Theparenthesestotheleftofxmakealist.)
5.6Createanarrayfromastring
@months = split ' ', "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
Here,@monthsisfilledwithvaluesfromthestringcontainingmonthnames.Becauseallmonthnamesareseparatedbyaspace,thesplitoperatorsplits
[email protected],$months[0]containsJan,$months[1]containsFeb,…,and$months[11]containsDec.
Youcoulddothesamethingwiththeqw/.../operator:
@months = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/
Theqw/.../operatortakesaspace-separatedstringandcreatesanarrayinwhicheachwordisanarrayelement.
Althoughnotaone-linerperse,thisisauseful,idiomaticwaytocreatearraysthatcancomeinhandywhenwritingone-liners.
5.7Createastringfromthecommand-linearguments
perl -le 'print "(", (join ",", @ARGV), ")"' val1 val2 val3
Thisone-linerusesthe@ARGVarray,whichcontainsalltheargumentsthathavebeenpassedtoPerl.Inthisone-liner,thevaluespassedtoPerlareval1,val2,andval3,so@ARGVcontainsthestringsval1,val2,andval3.Thisone-linerprintsthestring(val1,val2,val3)andwouldbeuseful,forexample,togenerateaSQLquery.
Ifyou’refamiliarwiththeINSERTqueryinSQL,youknowitsmostbasicformlookslikeINSERT INTO table VALUES (val1, val2, val3, ...).Asyoucansee,thisone-linergeneratestheVALUESpartoftheSQLquery.
Youcaneasilymodifythisone-linertoprintthewholeINSERTquery:
perl -le '
print "INSERT INTO table VALUES (", (join ",", @ARGV), ")"
' val1 val2 val3
Here’swhattheone-linerprints:
INSERT INTO table VALUES (val1,val2,val3)
5.8Findthenumericvaluesforcharactersinastring
perl -le 'print join ", ", map { ord } split //, "hello world"'
Thisone-linertakesthestring"hello world"andsplitsitintoalistofcharacterswithsplit //, "hello world".Itthenmapstheordoperatorontoeachofthecharacters,whichreturnseachcharacter’snumericvalue.Finally,allofthenumericvaluesarejoinedtogetherbyacommaandprinted.Here’stheoutput:
104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100
YoucouldalsodothiswiththeunpackoperatorbyspecifyingC*astheunpackingtemplate:
perl -le 'print join ", ", unpack("C*", "hello world")'
TheCinthetemplatemeans“unsignedcharacter”and*means“allcharacters.”
Tofindthehexadecimalvaluesofthecharacters,youcoulddothis:
perl -le '
print join ", ", map { sprintf "0x%x", ord $_ } split //, "hello world"
'
Here,themapoperatorexecutessprintf "0x%x", ord $_foreverycharacter,whichreturnsthecharacter’shexadecimalvalueprependedwith'0x'.Here’stheoutput:
0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64
Similarly,togettheoctalvaluesofcharacters,youdothis:
perl -le '
print join ", ", map { sprintf "%o", ord $_ } split //, "hello world"
'
Here’stheoutput:
150, 145, 154, 154, 157, 40, 167, 157, 162, 154, 144
Andfinally,togenerateproperoctalvaluesthatbeginwith0,youcanspecifythe%#oformattothesprintffunction:
perl -le '
print join ", ", map { sprintf "%#o", ord $_ } split //, "hello world"
'
Andhere’stheoutput:
0150, 0145, 0154, 0154, 0157, 040, 0167, 0157, 0162, 0154, 0144
5.9ConvertalistofnumericASCIIvaluesintoastring
perl -le '
@ascii = (99, 111, 100, 105, 110, 103);
print pack("C*", @ascii)
'
JustasIunpackedastringintoalistofvalueswiththeC*templateinthepreviousone-liner,Icanpackthemintoastringbyusingthesametemplate.Here’stheoutputfromtheone-liner:
coding
AnotherwaytoconvertalistofnumericASCIIvaluesintoastringistousethechroperator,whichtakesthecodepointvalueandreturnsthecorrespondingcharacter:
perl -le '
@ascii = (99, 111, 100, 105, 110, 103);
$str = join "", map chr, @ascii;
print $str
'
Here,yousimplymapthechroperatorontoeachnumericvalueinthe@asciiarray,whichproducesalistofcharactersthatcorrespondtothenumericvalues.Next,youjointhecharacterstogetherandproducethe$str,andthenyouprintitout.
Youcanalsogolfthisone-linerandcomeupwiththefollowing:
perl -le 'print map chr, 99, 111, 100, 105, 110, 103'
Youcanalsousethe@ARGVarrayandpasstheASCIIvaluesasargumentstotheone-liner:
perl -le 'print map chr, @ARGV' 99 111 100 105 110 103
5.10Generateanarraywithoddnumbersfrom1to100
perl -le '@odd = grep {$_ % 2 == 1} 1..100; print "@odd"'
Thisone-linergeneratesanarrayofoddnumbersfrom1to99(thatis,1,3,5,7,9,11,…,99).Itusesgreptoevaluatethecode$_ % 2 == 1foreachelementinthelist1..100andreturnsonlythoseelementsforwhichthegivencodeevaluatestotrue.Inthiscase,thecodeteststoseeiftheremainderwhendividingby2is1.Ifitis,thenumberisodd,andit’sputinthe@oddarray.
Youcouldalsowritethisusingthefactthatoddnumbershavetheleastsignificantbitsetandtestfortheleastsignificantbit:
perl -le '@odd = grep { $_ & 1 } 1..100; print "@odd"'
Theexpression$_ & 1isolatestheleastsignificantbit,andgrepselectsonlythosenumberswiththeleastsignificantbitset—thatis,alloddnumbers.
5.11Generateanarraywithevennumbersfrom1to100
perl -le '@even = grep {$_ % 2 == 0} 1..100; print "@even"'
Thisone-linerisalmostthesameastheonein5.10,exceptthatgreptestsforthecondition“isthenumbereven(remainderafterdividingbytwois0)?”
5.12Findthelengthofastring
perl -le 'print length "one-liners are great"'
Thelengthsubroutinefindsthelengthofastring.
5.13Findthenumberofelementsinanarray
perl -le '@array = ("a".."z"); print scalar @array'
Evaluatinganarrayinthescalarcontextreturnsitsnumberofelements.
Youcouldalsodothisbyadding1tothelastindexofanarray:
perl -le '@array = ("a".."z"); print $#array + 1'
Here,$#arrayreturnsthelastindexin@array.Becausethatnumberisonelessthanthenumberofelementsinthearray,youadd1totheresulttofindthetotalnumberofelementsinthearray.
Forexample,sayyouwanttofindouthowmanytextfilesareinthecurrentdirectory.Youcanuse@ARGVandpassthe*.txtwildcardtoPerl.Theshellexpandsthe*.txtwildcardtoalistoffilenamesthatmatch*.txt,andPerlputsthemintothe@ARGVarrayandprintsthearrayinthescalarcontext.Theoutputwillbethenumberoftextfilesinthecurrentdirectory:
perl -le 'print scalar @ARGV' *.txt
Ifyourshelldoesn’tsupportfilenameexpansion(alsoknownasglobbing)orifyou’reonWindows,youcanusethediamondoperatorwiththe*.txtargument:
perl -le 'print scalar (@ARGV=<*.txt>)'
Inthiscase,thediamondoperatordoestheglobbingandreturnsalistoffilenamesthatmatch*.txt.Evaluatingthislistinthescalarcontextreturnsthenumberoffilesthatmatched.
Chapter6.TextConversionandSubstitution
Inthischapter,we’lllookatvariousone-linersthatchange,convert,andsubstitutetext,includingbase64encodinganddecoding,URLescapingandunescaping,HTMLescapingandunescaping,convertingtextcase,andreversinglines.You’llalsogettoknowthey,tr,uc,lc,andreverseoperatorsandstring-escapesequences.
6.1ROT13astring
perl -le '$string = "bananas"; $string =~ y/A-Za-z/N-ZA-Mn-za-m/; print $string'
Thisone-linerusestheyoperator(alsoknownasthetroperator)todoROT13.Theoperatorsyandtrperformstringtransliteration.Giveny/search/replace/,theyoperatortransliteratesalloccurrencesofthecharactersfoundinthesearchlistwiththecharactersinthecorrespondingpositionsinthereplacelist.Theyandtroperatorsareoftenmistakenfortakingaregularexpression,buttheydon’t.Theytransliteratethingsandtakealistofcharactersinboththesearchandreplaceparts.
Inthisone-liner,A-Za-zcreatesthefollowinglistofcharacters:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
AndN-ZA-Mn-za-mcreatesthislist:
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
Noticethatinthesecondlisttheuppercaseandlowercasealphabetsareoffsetby
13characters.Nowtheyoperatortranslateseachcharacterinthefirstlisttoacharacterinthesecondlist,thusperformingtheROT13operation.(OnefunfactaboutROT13isthatapplyingittwiceproducesthesamestring;thatis,ROT13(ROT13(string))equalsstring.)
ToROT13thewholefilebananas.txtandprintittothescreen,justdothis:
perl -lpe 'y/A-Za-z/N-ZA-Mn-za-m/' bananas.txt
YoucanalsousePerl’s-iargumenttodoin-placereplacementofthefile.Forexample,toROT13oranges.txtin-place,writethis:
perl -pi.bak -e 'y/A-Za-z/N-ZA-Mn-za-m/' oranges.txt
Thisone-linerfirstcreatesabackupfilecalledoranges.txt.bakandthenreplacesthecontentsoforanges.txtwithROT13-edtext.The.bakpartofthe-icommandcreatesthebackupfile.Youcanomitthe.bakpartofthecommandifyou’resureabouttheresult,butIrecommendalwaysusing-i.bakbecauseonedayyoumightmakeamistakeandmessupanimportantfile.(Ispeakfromexperience.)
6.2Base64-encodeastring
perl -MMIME::Base64 -e 'print encode_base64("string")'
Thisone-linerusestheMIME::Base64module.Itexportstheencode_base64function,whichtakesastringandreturnsabase64-encodedversionofit.
Tobase64-encodethewholefile,usethis:
perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' file
Here,the-0777argumenttogetherwith-ncausesPerltoslurpthewholefileintothe$_variable.Next,thefileisbase64-encodedandprinted.(IfPerldidn’tslurptheentirefile,itwouldbeencodedlinebyline,andyou’dendupwithamess.)
6.3Base64-decodeastring
perl -MMIME::Base64 -le 'print decode_base64("base64string")'
TheMIME::Base64modulealsoexportsthedecode_base64function,whichtakesabase64-encodedstringanddecodesit.
Theentirefilecanbedecodedsimilarlywith
perl -MMIME::Base64 -0777 -ne 'print decode_base64($_)' file
6.4URL-escapeastring
perl -MURI::Escape -le 'print uri_escape("http://example.com")'
Tousethisone-liner,youneedtoinstalltheURI::Escapemodulefirstbyenteringcpan URI::Escapeintheshell.Themoduleexportstwofunctions:uri_escapeanduri_unescape.ThefirstfunctionperformsURLescaping(sometimesreferredtoasURLencoding),andtheotherdoesURLunescaping(orURLdecoding).Now,toURL-escapeastring,justcalluri_escape($string)andyou’redone!
Theoutputofthisone-linerishttp%3A%2F%2Fexample.com.
6.5URL-unescapeastring
perl -MURI::Escape -le 'print uri_unescape("http%3A%2F%2Fexample.com")'
Thisone-linerusestheuri_unescapefunctionfromtheURI::EscapemoduletoperformURLunescaping.Itunescapestheoutputofthepreviousone-linertoreversetheoperation.
Theoutputofthisone-linerishttp://example.com.
6.6HTML-encodeastring
perl -MHTML::Entities -le 'print encode_entities("<html>")'
Thisone-linerusestheencode_entitiesfunctionfromtheHTML::EntitiesmoduletoencodeHTMLentities.Forexample,youcanturn<and>into<and>.
6.7HTML-decodeastring
perl -MHTML::Entities -le 'print decode_entities("<html>")'
Thisone-linerusesthedecode_entitiesfunctionfromtheHTML::Entitiesmodule.Forexample,youcanturn<and>backinto<and>.
6.8Convertalltexttouppercase
perl -nle 'print uc'
Thisone-linerusestheucfunction,which,bydefault,operatesonthe$_variableandreturnsanuppercaseversionofthetextitcontains.
Youcoulddothesamethingwiththe-pcommand-lineoption,whichenablestheautomaticprintingofthe$_variableandmodifiesitin-place:
perl -ple '$_ = uc'
Oryoucanapplythe\Uescapesequencetostringinterpolation:
perl -nle 'print "\U$_"'
Thisone-lineruppercaseseverythingthatfollowsit(oreverythinguptothefirstoccurrenceof\E).
6.9Convertalltexttolowercase
perl -nle 'print lc'
perl -nle 'print lc'
Thisone-linerissimilartothepreviousone.Thelcfunctionconvertsthecontentsof$_tolowercase.
Youcouldalsousetheescapesequence\Landstringinterpolation:
perl -nle 'print "\L$_"'
Here,\Llowercaseseverythingafterit(oruntilthefirstinstanceof\E).
6.10Uppercaseonlythefirstletterofeachline
perl -nle 'print ucfirst lc'
Thisone-linerfirstlowercasestheinputwiththelcfunctionandthenusesucfirsttouppercaseonlythefirstcharacter.Forexample,ifyoupassitalinethatsaysfoobarbaz,itproducesthetextFoobarbaz.Similarly,ifyoupassitalineFOOBARBAZ,itlowercasesthelinefirstandthenuppercasesthefirstletter,producingFoobarbazagain.
Youcandothesamethingusingescapecodesandstringinterpolation:
perl -nle 'print "\u\L$_"'
First\Llowercasesthewholelineandthen\uuppercasesthefirstcharacter.
6.11Invertthelettercase
perl -ple 'y/A-Za-z/a-zA-Z/'
Thisone-linerchangesthecaseoftheletters:Thecapitallettersbecomelowercaseletters,andthelowercaselettersbecomecapitalletters.Forexample,thetextCowsareCOOLbecomescOWSAREcool.Thetransliterationoperatory(explainedinone-liner6.1onpage59)createsamappingfromcapitallettersA-Ztolowercaselettersa-zandamappingfromlowercaselettersa-ztocapital
lettersA-Z.
6.12Title-caseeachline
perl -ple 's/(\w+)/\u$1/g'
Thisone-linerattemptstotitle-caseastring,meaningthefirstletterofeachwordisuppercased;forexample,ThisTextIsWrittenInTitleCase.Thisone-linerworksbymatchingeverywordwith\w+andreplacingthematchedwordwith\u$1,whichuppercasesthefirstletteroftheword.
6.13Stripleadingwhitespace(spaces,tabs)fromthebeginningofeachline
perl -ple 's/^[ \t]+//'
Thisone-linerdeletesallwhitespacefromthebeginningofeverylinewiththehelpofthesubstitutionoperators.Givens/regex/replace/,itreplacesthematchedregexwiththereplacestring.Inthiscase,theregexis^[ \t]+,whichmeans“matchoneormorespacesortabsatthebeginningofthestring,”andreplaceisempty,meaning“replacethematchedpartwithanemptystring.”
Theregularexpressionclass[ \t]canalsobereplacedby\s+tomatchanywhitespace(includingtabsandspaces):
perl -ple 's/^\s+//'
6.14Striptrailingwhitespace(spaces,tabs)fromtheendofeachline
perl -ple 's/[ \t]+$//'
Thisone-linerdeletesallwhitespacefromtheendofeachline.Theregexofthe
soperatorsays“matchoneormorespacesortabsattheendofthestring.”Thereplacepartisemptyagain,whichmeans“erasethematchedwhitespace.”
Youcanalsoachievethesamebywriting:
perl -ple 's/\s+$//'
Here,youreplacewith[ \t]+$with\s+,asinone-liner6.13.
6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
perl -ple 's/^[ \t]+|[ \t]+$//g'
Thisone-linercombinesone-liners6.13and6.14.Itspecifiestheglobal/gflagtothesoperatorbecauseyouwantittodeletewhitespaceatthebeginningandtheendofthestring.Ifyoudon’tspecifythis,itdeleteswhitespaceonlyatthebeginning(ifthereiswhitespace)oronlyattheend(iftherewasnowhitespaceatthebeginning).
Youcanalsoreplace[ \t]+$with\s+andgetthesameresults:
perl -ple 's/^\s+|\s+$//g'
Writing\s+isshorterthanwriting[ \t]+.Andsstandsforspace,whichmakesiteasiertoremember.
6.16ConvertUNIXnewlinestoDOS/Windowsnewlines
perl -pe 's|\012|\015\012|'
Thisone-linersubstitutestheUNIXnewlinecharacter\012(LF)fortheWindows/DOSnewlinecharacter\015\012(CRLF)oneachline.Onenicefeatureofs/regex/replace/isthatitcantakecharactersotherthanforward
slashesasdelimiters.Here,itusesverticalpipestodelimitregexfromreplacetoimprovereadability.
Newlinesareusuallyrepresentedas\nandcarriagereturnsas\r,butacrossplatforms,themeaningsofthe\nand\rsequencescanvary.TheUNIXnewlinecharacter,however,isalwaysavailableas\012(LF),andthecarriage-returncharacterrepresentedby\risalwaysavailableas\015(CR).That’swhyyouusethosenumericcodes:Sometimesusingtheflexiblesequenceispreferable,butnothere.
6.17ConvertDOS/WindowsnewlinestoUNIXnewlines
perl -pe 's|\015\012|\012|'
Thisone-linerworksintheoppositedirectionfromone-liner6.16.IttakesWindowsnewlines(CRLF)andconvertsthemtoUNIXnewlines(LF).
6.18ConvertUNIXnewlinestoMacnewlines
perl -pe 's|\012|\015|'
MacOSpreviouslyused\015(CR)asnewlines.Thisone-linerconvertsUNIX’s\012(LF)toMacOS’s\015(CR).
6.19Substitute(findandreplace)“foo”with“bar”oneachline
perl -pe 's/foo/bar/'
Thisone-linerusesthes/regex/replace/commandtosubstitutethefirstoccurrenceoffoowithbaroneachline.
Toreplaceallfooswithbars,addtheglobal/gflag:
perl -pe 's/foo/bar/g'
6.20Substitute(findandreplace)“foo”with“bar”onlinesthatmatch“baz”
perl -pe '/baz/ && s/foo/bar/'
Thisone-linerisroughlyequivalentto
while (defined($line = <>)) {
if ($line =~ /baz/) {
$line =~ s/foo/bar/
}
}
Thisexpandedcodeputseachlineintothevariable$lineandthencheckstoseeifalineinthatvariablematchesbaz.Ifso,itreplacesfoowithbarinthatline.
Youcouldalsowrite
perl -pe 's/foo/bar/ if /baz/'
6.21Printparagraphsinreverseorder
perl -00 -e 'print reverse <>' file
Thisone-linerusesthe-00argumentdiscussedinone-liner2.7(page14)toturnparagraphslurpmodeon,meaningthatPerlreadstextparagraphbyparagraph,ratherthanlinebyline.Next,itusesthe<>operatortomakePerlreadtheinputfromeitherstandardinputorfilesspecifiedasarguments.Here,I’vespecifiedfileastheargumentsoPerlwillreadfileparagraphbyparagraph(thanksto-00).OncePerlfinishesreadingthefile,itreturnsallparagraphsasalistandcallsreversetoreversetheorderoftheparagraphlist.Finally,printprintsthelistofreversedparagraphs.
6.22Printalllinesinreverseorder
perl -lne 'print scalar reverse $_'
Thisone-linerevaluatesthereverseoperatorinthescalarcontext.Inthepreviousone-liner,yousawthatevaluatingreverseinthelistcontextreversesthewholelist,thatis,theorderoftheelements.Todothesameforscalarvaluessuchas$_thatcontainthewholeline,youhavetocallreverseinthescalarcontext.Otherwise,itsimplyreversesalistwithonlyoneelement,whichisthesamelist!Onceyou’vedonethat,yousimplyprintthereversedline.
Oftenyoucandropthe$_variablewhenusingoperatorsandPerlwillstillapplythefunctiononthe$_variable.Inotherwords,youcanrewritethesameone-lineras
perl -lne 'print scalar reverse'
Oryoucansubstitute-nfor-p,modifythe$_variable,andsetitsvaluetoreverse:
perl -lpe '$_ = reverse $_'
Youcanalsowritethisas
perl -lpe '$_ = reverse'
Here,$_isdroppedbecausemostPerloperatorsdefaultto$_whennotgivenanargument.
6.23Printcolumnsinreverseorder
perl -alne 'print "@{[reverse @F]}"'
Thisone-linerreversestheorderofcolumnsinafile.The-acommand-lineargumentsplitseachlineintocolumnsatspacesandputstheminthe@Farray,
whichisthenreversedandprinted.Thisone-linerissimilartoone-liner4.4onpage32;Iexplainedthe@{[ ... ]}constructthere.Itsimplyletsyouruncodeinsideofdoublequotes.Forexample,giventhefollowinginputfile:
one two three four
five six seven eight
theone-linerreversestheorderofthecolumns,andtheoutputisthefollowing:
four three two one
eight seven six five
Ifthecolumnsinyourinputareseparatedbyanycharacterotherthanaspace,youcanusethe-Fcommand-lineargumenttosetadifferentdelimiter.Forexample,giventhefollowinginputfile:
one:two:three:four
five:six:seven:eight
youcanaddthe-F:command-lineargumenttotheone-linerlikethis:
perl -F: -alne 'print "@{[reverse @F]}"'
anditproducesthisoutput:
four three two one
eight seven six five
Notice,however,thatthe:charactersaremissinginthisoutput.Togetthemback,youneedtomodifytheone-linerabitandsetthe$"variableto":",asshownhere:
perl -F: -alne '$" = ":"; print "@{[reverse @F]}"'
Thisproducestheexpectedoutput:
four:three:two:one
eight:seven:six:five
The$"variablechangesthecharacterthat’sprintedbetweenarrayelementswhenanarrayisinterpolatedwithinadouble-quotedstring.
Chapter7.SelectivelyPrintingandDeletingLines
Inthischapter,we’llexaminevariousone-linersthatprintanddeletecertainlines.Theseone-linerswill,forexample,printrepeatedlines,printtheshortestlineinafile,andprintlinesthatmatchcertainpatterns.
Buteveryone-linerthatprintscertainlinescanalsobeviewedasonethatdeletesthelinesthataren’tprinted.Forexample,aone-linerthatprintsalluniquelinesdeletesallrepeatedlines.I’lldiscussonlytheone-linersthatprintsomething,ratherthandeletesomething,becauseoneisalwaystheinverseoftheother.
7.1Printthefirstlineofafile(emulatehead-1)
perl -ne 'print; exit' file
Thisone-linerisquitesimple.Perlreadsthefirstlineintothe$_variable,thankstothe-noption,andthencallsprinttoprintthecontentsofthe$_variable.Thenitjustexits.That’sit.Thefirstlineisprintedandthat’swhatyouwant.
Youmightalsosaythatthisone-linerdeletesalllinesexceptthefirstone.Butdon’tworry.Thisparticularone-linerwon’tdeletethecontentsofthefileunlessyoualsospecifythe-icommand-lineargument,likethis:
perl -i -ne 'print; exit' file
AsIexplainedinChapter1andinone-liner6.1onpage59,the-iargumenteditsthefilein-place.Inthiscase,allthelinesinthefilewouldbedeletedexceptforthefirst.Whenusing-i,alwaysspecifyabackupextensiontoit,likethis:
perl -i.bak -ne 'print; exit' file
Thiswillcreateabackupfilefile.bakbeforethecontentsareoverwritten.
Youcanaddthe-icommand-lineargumenttoanyoftheone-linerstochangethefilecontent.Ifyoudon’tusethe-iargument,theone-linerssimplyprintthenewcontentofthefiletoscreenratherthanmodifyingthefile.
7.2Printthefirst10linesofafile(emulatehead-10)
perl -ne 'print if $. <= 10' file
Thisone-linerusesthe$.specialvariable,whichstandsfor“thecurrentlinenumber.”EachtimePerlreadsinaline,itincrements$.by1,soclearlythisone-linersimplyprintsthefirst10lines.
Thisone-linercanalsobewrittenwithouttheifstatement:
perl -ne '$. <= 10 && print' file
Here,printiscalledonlyiftheBooleanexpression$. <= 10istrue,andthisexpressionistrueonlyifthecurrentlinenumberislessthanorequalto10.
Another,thoughsomewhattrickier,waytodothisiswiththerangeoperator(..)inthescalarcontext:
perl -ne 'print if 1..10' file
TherangeoperatorinthescalarcontextreturnsaBooleanvalue.Theoperatorisbistable,likeaflip-flop,andemulatestheline-range(comma)operatorinsed,awk,andvarioustexteditors.Itsvalueisfalseaslongasitsleftoperandisfalse.Oncetheleftoperandistrue,therangeoperatoristrueuntiltherightoperandistrue,afterwhichtherangeoperatorbecomesfalseagain.Asaresult,thisbistableoperatorbecomestrueatthefirstline,staystrueuntilthetenthline,andthenbecomesandremainsfalse.
Afourthoptionistofollowthefirstexampleinthischapter:
Afourthoptionistofollowthefirstexampleinthischapter:
perl -ne 'print; exit if $. == 10' file
Here,Iputaconditiononexit,whichisthatthecurrentline(whichIjustprinted)isnumber10.
7.3Printthelastlineofafile(emulatetail-1)
perl -ne '$last = $_; END { print $last }' file
Printingthelastlineofafileistrickierthanprintingthefirstline,becauseyouneverknowwhichisthelastline.Asaresult,youalwayshavetokeepthelineyoujustreadinmemory.Inthisone-liner,youalwayssavethecurrentlineheldin$_intothe$lastvariable.WhenthePerlprogramends,itexecutesthecodeintheENDblock,whichprintsthelastlineread.
Here’sanotherwaytodothis:
perl -ne 'print if eof' file
Thisone-linerusestheeof(orend-of-file)function,whichreturns1ifthenextreadreturnstheend-of-file.Becausethenextreadafterthelastlineinthefilewillreturntheend-of-file,thisone-linerdoesthejob.ThenextreadmeansthatPerlwillattempttoreadacharacterfromthecurrentfile,andifreadingthecharacterfails,itwillsignalthattheend-of-filehasbeenreached,meaningthewholefilehasbeenread.Ifthereadsucceeds,Perlsecretlyputsthecharacterbackintheinputstreamasifnothinghadhappened.
7.4Printthelast10linesofafile(emulatetail-10)
perl -ne 'push @a, $_; @a = @a[@a-10..$#a] if @a>10; END { print @a }' file
Thisone-linerisabittricky.Here,youpusheachlinetothe@aarrayandthen
replace@awithasliceofitselfifthelistcontainsmorethan10elements.Thephrase@a = @a[@a-10..$#a]means“replace@awiththelast10elementsof@a.”Thebit@a-10causes@atobeevaluatedinthescalarcontext,andthusitreturnsthenumberofelementsinthearrayminus10.Theexpression$#[email protected],@a[@a-10..$#a]slices(returns)thelast10elementsofthearray,withwhichitoverwrites@aitselfsoitalwayscontainsonlythelast10elements.
Forexample,suppose@acontains(line1, line2, line3, line4),andyouwanttoprintthelastfourlinesofthefile.Whenyoureadthefifthline,thearraybecomes(line1, line2, line3, line4, line5),andthevalueof@[email protected]$#ais4becauseit’sthelastindexinthearray.Thereforewhenyoutaketheslice@a[@a-4..$#a],itbecomes@a[1..4],whichdropsthefrontelementfromthearray,andthe@aarraybecomes(line2, line3, line4, line5).
Asimplerwaytowritethisiswithshift:
perl -ne 'push @a, $_; shift @a if @a>10; END { print @a }' file
Thisone-linerdoesn’tneedtoslice@abecauseyoucanguaranteethatif@a >10,then@a == 11.shiftisanoperatorthatremovesthefirstelementofanarray.Sointhisloop,youcansimplyshiftoffthefirststoredlinewhenyouhavemorethan10lines.
7.5Printonlylinesthatmatcharegularexpression
perl -ne '/regex/ && print'
Thisone-linerteststoseewhetherthecurrentlinematches/regex/.Ifso,the/regex/matchsucceedsandprintiscalled.
Insteadofusing&&,youcanalsouseiftoreversethe/regex/andprintstatements:
perl -ne 'print if /regex/'
7.6Printonlylinesthatdonotmatcharegularexpression
perl -ne '!/regex/ && print'
Thisone-linerinvertsthepreviousone-liner.Here,Itesttoseethatthelinedoesn’tmatch/regex/byinvertingthematchviathe!operator.Ifthelinedoesn’tmatch,Icallprinttoprinttheline.
Youcanalsowritethistheotherwayaround:
perl -ne 'print if !/regex/'
Andyoucanalsouseunlessinsteadofif !:
perl -ne 'print unless /regex/'
AnotherwaytowritethisistoapplyDeMorgan’slawto!/regex/ && print:
perl -ne '/regex/ || print'
7.7Printeverylineprecedingalinethatmatchesaregularexpression
perl -ne '/regex/ && $last && print $last; $last = $_'
Thisone-linerprintsalinewhenitisabovealinethatmatches/regex/.Let’swalkthroughit,beginningatthelaststatement,$last = $_,whichsaveseachlineinthe$lastvariable.Supposethenextlineisreadanditmatches/regex/.Becausethepreviouslineissavedin$last,theone-linersimplyprintsit.Theseriesof&&meansfirstthattheregularexpressionmustmatchandsecondthat$lastmustbeatruevalue.(Blanklinesarestillprintedbecausetheycontain
thenewlinecharacter.)
Sayyouhaveafilewithfourlines:
hello world
magic line
bye world
magic line
andyouwanttoprintalllinesabovethosethatmatchmagic.Youcandothis:
perl -ne '/magic/ && $last && print $last; $last = $_'
andtheone-linerwillprint:
hello world
bye world
7.8Printeverylinefollowingalinethatmatchesaregularexpression
perl -ne 'if ($p) { print; $p = 0 } $p++ if /regex/'
Here,Isetthevariable$pto1ifthecurrentlinematchestheregularexpression.Thefactthatthevariable$pis1indicatesthatthenextlineshouldbeprinted.Now,whenthenextlineisreadinand$pisset,thatlineisprintedand$pisresetto0.Quitesimple.
Let’ssayyouhavethisfour-linefile:
science
physics
science
math
andyouwanttoprintalllinesbelowthosethatmatchscience.Dothis:
perl -ne 'if ($p) { print; $p = 0 } $p++ if /science/'
Theone-linerwillprint:
physics
math
Ifyouwanttowritethiswith&&andavoidusingifandcurlybrackets,dothis:
perl -ne '$p && print && ($p = 0); $p++ if /science/'
Youcanalsobeverysmartaboutthisandsimplifythisone-linertothefollowing:
perl -ne '$p && print; $p = /science/'
Ifthecurrentlinematchesscience,thenvariable$pissettoatruevalueandthenextlinegetsprinted.Ifthecurrentlinedoesn’tmatchscience,then$pbecomesundefinedandthenextlinedoesn’tgetprinted.
7.9PrintlinesthatmatchregularexpressionsAAAandBBBinanyorder
perl -ne '/AAA/ && /BBB/ && print'
Thisone-linerteststoseewhetheralinematchestworegularexpressions.Ifalinematches/AAA/and/BBB/,it’sprinted.Specifically,thisone-linerprintsthelinefooAAAbarBBBbazbecauseitcontainsbothAAAandBBB,butitwon’tprintthelinefooAAAbarAAAbecauseitdoesn’tcontainBBB.
7.10Printlinesthatdon’tmatchregularexpressionsAAAandBBB
perl -ne '!/AAA/ && !/BBB/ && print'
Thisone-linerisalmostthesameasthepreviousone.Here,Itesttoseeifaline
doesn’tmatchbothregularexpressions.Ifitdoesn’tmatch/AAA/or/BBB/,itprints.
7.11PrintlinesthatmatchregularexpressionAAAfollowedbyBBBfollowedbyCCC
perl -ne '/AAA.*BBB.*CCC/ && print'
Here,IsimplychaintheregularexpressionsAAA,BBB,andCCCwith.*,whichmeans“matchanythingornothingatall.”IfAAAisfollowedbyBBB,whichisfollowedbyCCC,thelineprints.Forexample,thisone-linermatchesandprintsstringslike123AAA880BBB222CCC,xAAAyBBBzCCC,andAAABBBCCC.
7.12Printlinesthatareatleast80characterslong
perl -ne 'print if length >= 80'
Thisone-linerprintsalllinesthatareatleast80characterslong.InPerl,youcansometimesomittheparentheses()forfunctioncalls,sohereI’veomittedthemforthelengthfunctioncall.Infact,theinvocationslength,length(),andlength($_)areallthesameasfarasPerlisconcerned.
Ifyoudon’twanttocountlineendings,youcanturnonautomatichandlingoflineendingswith-l:
perl -lne 'print if length >= 80'
Thisswitchensuresthatablanklinehaszerolength,whereasitusuallyhaslength1or2,dependingonthefileformat.(UNIXnewlineshavelength1;Windowsnewlineshavelength2.)
7.13Printlinesthatarefewerthan80characterslong
long
perl -ne 'print if length() < 80'
Thisone-linerreversesthepreviousone.Itcheckstoseewhetherthelengthofalineislessthan80characters.Again,youuse-lifyoudon’twantthelineendingstobecounted.
7.14Printonlyline13
perl -ne '$. == 13 && print && exit'
AsIexplainedinone-liner7.2onpage70,the$.specialvariablestandsfor“thecurrentlinenumber.”Therefore,if$.hasavalueof13,thisone-linerprintsthelineandexits.
7.15Printalllinesexceptline27
perl -ne '$. != 27 && print'
Asinthepreviousone-liner,thisonecheckstoseewhetherthelinenumberofthecurrentlineis27.Ifalineisnot27,itprints;ifitis,itdoesn’tprint.
Youcanaccomplishthesamethingbyreversingprintand$. != 27andusingtheifstatementmodifier—justlikethis:
perl -ne 'print if $. != 27'
Oryoucanuseunless:
perl -ne 'print unless $. == 27'
7.16Printonlylines13,19,and67
perl -ne 'print if $. == 13 || $. == 19 || $. == 67'
perl -ne 'print if $. == 13 || $. == 19 || $. == 67'
Thisone-linerprintsonlylines13,19,and67.Itdoesn’tprintanyotherlines.Here’showitworks:Itcallsprintifthecurrentlinenumber,storedinthe$.variable,is13,19,or67.Youcanuseanylinenumberstoprintspecificlines.Forexample,toprintthelines13,19,88,290,and999,youdothis:
perl -ne 'print if $. == 13 || $. == 19 || $. == 88 || $. == 290 || $. == 999'
Ifyouwanttoprintmorelines,youcanputtheminaseparatearrayandthentestwhether$.isinthisarray:
perl -ne '
@lines = (13, 19, 88, 290, 999, 1400, 2000);
print if grep { $_ == $. } @lines
'
Thisone-linerusesgreptotestifthecurrentline$.isinthe@linesarray.Ifthecurrentlinenumberisfoundinthe@linesarray,thegrepfunctionreturnsalistofoneelementthatcontainsthecurrentlinenumberandthislistevaluatestotrue.Ifthecurrentlinenumberisnotfoundinthe@linesarray,thegrepfunctionreturnsanemptylistthatevaluatestofalse.
7.17Printalllinesfrom17to30
perl -ne 'print if $. >= 17 && $. <= 30'
Inthisone-liner,the$.variablestandsforthecurrentlinenumber.Asaresult,theone-linercheckstoseewhetherthecurrentlinenumberisgreaterthanorequalto17andlessthanorequalto30.
Youcandothesamethingusingtheflip-flopoperator,whichisexplainedinone-liner7.2onpage70.Theflip-flopoperatoroperateson$.whenusedwithintegers:
perl -ne 'print if 17..30'
7.18Printalllinesbetweentworegular
7.18Printalllinesbetweentworegularexpressions(includingthelinesthatmatch)
perl -ne 'print if /regex1/../regex2/'
Thisone-linerusestheflip-flopoperator(explainedinone-liner7.2onpage70).Whenusedwithintegers,theoperandsaretestedagainstthe$.variable.Whenusedwithregularexpressions,theoperandsaretestedagainstthecurrentline,storedinthe$_variable.Initiallytheoperatorreturnsfalse.Whenalinematchesregex1,theoperatorflipsandstartsreturningtrueuntilanotherlinematchesregex2.Atthatpoint,theoperatorreturnstrueforthelasttimeandthenflipstothefalsestate.Fromnowontheoperatorreturnsfalse.Thisone-liner,therefore,printsalllinesbetween(andincluding)thelinesthatmatchregex1andregex2.
7.19Printthelongestline
perl -ne '
$l = $_ if length($_) > length($l);
END { print $l }
'
Thisone-linerkeepsthelongestlineseensofarinthe$lvariable.Ifthelengthofthecurrentline$_exceedsthelengthofthelongestline,thevaluein$lisreplacedwiththevalueofthecurrentline.Beforeexiting,theENDblockisexecuted,anditprintsthelongestlinevaluethat’sheldin$l.
Remembertouse-lifyouwanttopreventthenewlinecharactersfromcountingtowardthelinelength.
7.20Printtheshortestline
perl -ne '
$s = $_ if $. == 1;
$s = $_ if length($_) < length($s);
END { print $s }
'
Thisone-lineristheoppositeofthepreviousone.Becauseit’sfindingtheshortestlineand$sisnotdefinedforthefirstline,youhavetosetitsvaluetothefirstlineexplicitlythrough$s = $_ if $. == 1.Thenitsimplydoestheoppositeofthepreviousone-liner.Thatis,itcheckstoseewhetherthecurrentlineistheshortestlinesofarand,ifso,assignsitto$s.
7.21Printalllinescontainingdigits
perl -ne 'print if /\d/'
Thisone-linerusestheregularexpression\d(whichstandsfor“adigit”)toseewhetheralinecontainsadigit.Ifso,thechecksucceeds,andthelineisprinted.Forexample,thislinewouldbeprintedbecauseitcontainsdigits:
coding is as easy as 123
However,thislinewouldn’tbeprintedbecauseitdoesn’tcontaindigits:
coding is as easy as pie
7.22Printalllinescontainingonlydigits
perl -ne 'print if /^\d+$/'
Inthisone-liner,theregularexpression^\d+$means“matchalineifitcontainsonlydigitsfromthebeginninguntiltheend.”Forexample,thislinewouldbeprintedbecauseitcontainsonlydigits:
3883737189170238912377
However,thislinewouldn’tbeprintedbecauseitalsocontainssomecharacters:
8388338 foo bar random data 999
Youcanalsoinvertthe^\d$regularexpressionanduse\D:
perl -lne 'print unless /\D/'
Thisone-linerisgreatfordevelopingyourlogicalreasoningbecauseituseslogicalnegationtwice.Here,thelineprintsonlyifitdoesnotcontainanon-numericcharacter.Inotherwords,itprintsonlyifallthecharactersarenumeric.(NoticethatIusedthe-lcommand-lineargumentforthisone-linerbecauseofthenewlinecharacterattheendoftheline.IfIdidn’tuse-l,thelinewouldcontainthenewlinecharacter—anon-numericcharacter—anditwouldn’tbeprinted.)
7.23Printalllinescontainingonlyalphabeticcharacters
perl -ne 'print if /^[[:alpha:]]+$/
Thisone-linercheckstoseewhetheralinecontainsonlyalphabeticcharacters.Ifso,itprintstheline.The[[:alpha:]]standsfor“anyalphabeticcharacter.”And[[:alpha:]]+standsfor“allalphabeticcharacters.”
7.24Printeverysecondline
perl -ne 'print if $. % 2'
Thisone-linerprintsthefirst,third,fifth,andseventhlines(andsoon).Itdoessobecause$. % 2istruewhenthecurrentlinenumberisoddandfalsewhenthecurrentlinenumberiseven.
7.25Printeverysecondline,beginningwiththesecondline
perl -ne 'print if $. % 2 == 0'
Thisone-linerislikepreviousone,exceptitprintsthesecond,fourth,sixth,andeighthlines(andsoon)because$. % 2 == 0istruewhenthecurrentlinenumberiseven.
Alternatively,youcansimplyinvertthetestfromthepreviousexample:
perl -ne 'print unless $. % 2'
7.26Printallrepeatedlinesonlyonce
perl -ne 'print if ++$a{$_} == 2'
Thisone-linertracksthelinesithasseensofarandcountsthenumberoftimesithasseenthelinespreviously.Ifitseesalineasecondtime,itprintsthelinebecause++$a{$_} == 2istrue.Ifitseesalinemorethantwotimes,itdoesnothingbecausethecountforthislineisgreaterthan2.
7.27Printalluniquelines
perl -ne 'print unless $a{$_}++'
Thisone-linerprintsalineonlyifthehashvalue$a{$_}forthatlineisfalse.EverytimePerlreadsinaline,itincrements$a{$_},whichensuresthatthisone-linerprintsonlynever-before-seenlines.
Chapter8.UsefulRegularExpressions
Inthischapter,we’lllookatvariousregularexpressionsandhowtousetheminsomehandyone-liners.TheregularexpressionsincludematchingIPaddresses,HTTPheaders,andemailaddresses;matchingnumbersandnumberranges;andextractingandchangingmatches.I’llalsosharesomeregularexpressionpuzzlesandbestpractices.ThischapterwillbeabitdifferentfrompreviousonesbecauseI’llstartwitharegularexpressionandthenwriteaone-linerthatusesit.
8.1MatchsomethingthatlookslikeanIPaddress
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
Thisregularexpressiondoesn’tactuallyguaranteethatthethingthatmatchedis,infact,avalidIP;itsimplymatchessomethingthatlookslikeanIPaddress.Forexample,itmatchesavalidIPsuchas81.198.240.140aswellasaninvalidIPsuchas936.345.643.21.
Here’showitworks.The^atthebeginningoftheregularexpressionisananchorthatmatchesthebeginningofthestring.Next,\d{1,3}matchesone,two,orthreeconsecutivedigits.The\.matchesadot.The$attheendisananchorthatmatchestheendofthestring.(Youuseboth^and$anchorstopreventstringslikefoo213.3.1.2barfrommatching.)
Youcansimplifythisregularexpressionbygroupingthefirstthreerepeated\d{1,3}\.expressions:
/^(\d{1,3}\.){3}\d{1,3}$/
Sayyouhaveafilewiththefollowingcontentandyouwanttoextractonlythe
SayyouhaveafilewiththefollowingcontentandyouwanttoextractonlythelinesthatlooklikeIPaddresses:
81.198.240.140
1.2.3.4
5.5
444.444.444.444
90.9000.90000.90000
127.0.0.1
Toextractonlythematchinglines,youcanwritethis:
perl -ne 'print if /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/'
whichshouldprint
81.198.240.140
1.2.3.4
444.444.444.444
127.0.0.1
One-liner8.3explainshowtomatchanIPprecisely,notjustsomethingthatlookslikeanIP.
8.2Testwhetheranumberisintherange0to255
/^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/
Iliketochallengepeoplewithpuzzles.Oneofmyfavoritesistoasksomeonetocomeupwitharegularexpressionthatmatchesanumberrange.Writingoneisactuallyquitetrickyifyou’veneverdonesobefore.
Here’showitworks.Anumbercanhaveone,two,orthreedigits.Ifthenumberhasonedigit,youallowittobeanything[0-9].Ifithastwodigits,youalsoletitbeanycombinationof[0-9][0-9].Butifthenumberhasthreedigits,ithastobeeitheronehundred–somethingortwohundred–something.Ifthenumberisonehundred–something,1[0-9][0-9]matchesit.Ifthenumberistwo
hundred–something,thenumberiseither200to249(whichismatchedby2[0-4][0-9])orit’s250to255(whichismatchedby25[0-5]).
Let’sconfirmthisregularexpressionreallymatchesallnumbersintherange0to255andwriteaone-linertodoit:
perl -le '
map { $n++ if /^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/ } 0..255;
END { print $n }
'
Thisone-lineroutputs256,thetotalnumbersintherange0to255.Ititeratesovertherange0to255andincrementsthe$nvariableforeverynumberthatmatches.Iftheoutputvaluewaslessthan256,you’dknowthatsomenumbersdidn’tmatch.
Let’salsomakesurethisone-linerdoesn’tmatchnumbersabove255:
perl -le '
map { $n++ if /^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/ } 0..1000;
END { print $n }
'
Althoughthereare1001iterations,from0to1000,thefinalvalueof$nandtheoutputshouldstillbe256becausenumbersgreaterthan255shouldnotmatch.Ifthevaluewasgreaterthan256,you’dknowthattoomanynumbersmatchedandtheregularexpressionwasincorrect.
8.3MatchanIPaddress
my $ip_part = qr/[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]/;
if ($ip =~ /^$ip_part\.$ip_part\.$ip_part\.$ip_part$/) {
print "valid ip\n";
}
Thisregularexpressioncombinestheideasfromtheprevioustworegularexpressions(8.1and8.2)andintroducestheqr/.../operator,whichletsyouconstructaregularexpressionandsaveitinavariable.Here,I’msavingthe
regularexpressionthatmatchesallnumbersintherange0to255inthe$ip_partvariable.Next,the$ip_partmatchesthefourpartsoftheIPaddress.
YoucansimplifythisbygroupingthefirstthreeIPparts:
if ($ip =~ /^($ip_part\.){3}$ip_part$/) {
print "valid ip\n";
}
Let’srunthisonthesamefilefromone-liner8.1.Ifyouhavethisfileasinput:
81.198.240.140
1.2.3.4
5.5
444.444.444.444
90.9000.90000.90000
127.0.0.1
andyourone-lineris
perl -ne '
$ip_part = qr|([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|;
print if /^($ip_part\.){3}$ip_part$/
'
thentheoutputis
81.198.240.140
1.2.3.4
127.0.0.1
Asyoucansee,onlythevalidIPaddressesareprinted.
8.4Checkwhetherastringlookslikeanemailaddress
/\S+@\S+\.\S+/
Thisregularexpressionmakessurethestringlookslikeanemailaddress;it
doesn’tguaranteethestringisanemailaddress,however.First,itmatchessomethingthat’snotwhitespace(\S+)uptothe@symbol;thenitmatchesasmuchaspossibleuntilitfindsadot;thenitmatchessomemore.
Ifthematchessucceed,youknowthestringatleastlookslikeanemailaddresswiththe@symbolandadotinit.Forexample,[email protected],butcats@catonmatdoesn’tbecausetheregularexpressioncan’tfindthedotthat’srequiredinafullyqualifieddomainname.
Here’samuchmorerobustwaytoseewhetherastringisavalidemailaddress,usingtheEmail::Validmodule:
use Email::Valid;
print Email::Valid->address('[email protected]') ? 'valid email' : 'invalid email';
Here,youusetheternaryoperatorcond ? true : false.Ifthecondistrue,thetruepartexecutes;otherwisethefalsepartexecutes.Thisprintsvalidemailiftheemailisvalid;ifnot,itprintsinvalid email.
Soaone-linerwouldlooklikethis:
perl -MEmail::Valid -ne 'print if Email::Valid->address($_)'
Here,iftheemailaddressisvalid,yousimplyprintit.
8.5CheckwhetherastringisanumberDeterminingwhetherastringisanumberisdifficultwitharegularexpression.Thisisaderivationofaregularexpressionthatmatchesdecimalnumbers.
IstartwithPerl’s\dregularexpression,whichmatchesthedigits0through9:
/^\d+$/
Thisregularexpressionmatchesoneormoredigits\dfromthebeginningofthestring^totheendat$.Butitdoesn’tmatchnumberssuchas+3and-3.Let’smodifytheregularexpressiontomatchthem:
/^[+-]?\d+$/
/^[+-]?\d+$/
Here,the[+-]?means“matchanoptionalplusoraminusbeforethedigits.”Thisregularexpressionnowmatches+3and-3butnot-0.3.Let’saddthat:
/^[+-]?\d+\.?\d*$/
I’veexpandedthepreviousregularexpressionbyadding\.?\d*,whichmatchesanoptionaldotfollowedbyzeroormorenumbers.Nowwe’reinbusiness.Thisregularexpressionalsomatchesnumberslike-0.3and0.3,thoughitwouldnotmatchnumberssuchas123,456or.5.
AmuchbetterwaytomatchadecimalnumberistousetheRegexp::Commonmodule.Forexample,tomatchadecimalnumber,youcanuse$RE{num}{real}fromRegexp::Common.Here’saone-linerthatfilterstheinputandprintsonlythedecimalnumbers:
perl -MRegexp::Common -ne 'print if /$RE{num}{real}/'
Thisone-lineralsomatchesandprintsnumberssuchas123,456and.5.
Howaboutmatchingpositivehexadecimalnumbers?Here’show:
/^0x[0-9a-f]+$/i
Thisone-linermatchesthehexprefix0xfollowedbythehexnumberitself.The/iflagattheendensuresthematchiscaseinsensitive.Forexample,0x5afmatches,0X5Famatches,but97doesn’tbecause97hasnohexprefix.
Betterstill,use$RE{num}{hex}becauseitsupportsnegativenumbers,decimalplaces,andnumbergrouping.
Howaboutmatchingoctals?
/^0[0-7]+$/
Octalnumbersareprefixedby0,whichisfollowedbytheoctaldigits0-7.Forexample,013matchesbut09doesn’tbecauseit’snotavalidoctalnumber.Using$RE{num}{oct}isbetterbecauseitsupportsnegativeoctalnumbers,octal
numberswithdecimalplaces,andnumbergrouping.
Finally,wecometobinarymatching:
/^[01]+$/
Binarybaseconsistsofonly0sand1s,so010101matchesbut210101doesn’tbecause2isnotavalidbinarydigit.
Regexp::Commonalsooffersabetterregularexpressionformatchingbinarynumbers:$RE{num}{bin}.
8.6Checkwhetherawordappearsinastringtwice
/(word).*\1/
Thisregularexpressionmatchesawordfollowedbysomethingornothingatall,followedbythesameword.Here,(word)capturesthewordingroup1,and\1referstothecontentsofgroup1,whichisthesameaswriting/(word).*word/.Forexample,silly things are sillymatches/(silly).*\1/,butsillythings are boringdoesn’tbecausesillyisnotrepeatedinthestring.
8.7Increaseallintegersinastringbyone
$str =~ s/(\d+)/$1+1/ge
Here,youusethesubstitutionoperatorstomatchallintegers(\d+),putthemincapturegroup1,andthenreplacethemwiththeirvalueincrementedbyone:$1+1.Thegflagfindsallnumbersinthestring,andtheeflagevaluates$1+1asaPerlexpression.Forexample,this 1234 is awesome 444isturnedintothis 1235 is awesome 445.
Notethatthisregularexpressiondoesn’tincrementfloating-pointnumbersbecauseituses\d+tomatchintegers.Toincrementfloating-pointnumbers,use
the$RE{num}{real}regularexpressionfromone-liner8.5.Here’sasampleone-linerthatuses$RE{num}{real}:
perl -MRegexp::Common -pe 's/($RE{num}{real})/$1+1/ge'
Ifyoupassthisone-linertheinputweird 44.5 line -1.25,itprintsweird45.5 line -0.25.
8.8ExtracttheHTTPUser-AgentstringfromHTTPheaders
/^User-Agent: (.+)$/
HTTPheadersareformattedasKey: Valuepairs.YoucaneasilyparsesuchstringsbyinstructingtheregularexpressionenginetosavetheValuepartinthe$1groupvariable.Forexample,iftheHTTPheaderscontainthefollowing:
Host: www.catonmat.net
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_0_0; en-US)
Accept: application/xml,application/xhtml+xml,text/html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
thentheregularexpressionwillextractthestringMozilla/5.0 (Macintosh;U; Intel Mac OS X 10_0_0; en-US).
8.9MatchprintableASCIIcharacters
/[ -~]/
Thisregularexpressionistrickyandsmart.Tounderstandit,takealookatmanascii,andyou’llseethatspacestartsatvalue0x20andthe~characteris0x7e.Theexpression[ -~]definesarangeofcharactersfromthespaceuntil~.
Becauseallcharactersbetweenthespaceand~areprintable,thisregularexpressionmatchesallprintablecharacters.Thisismyfavoriteregularexpressionofalltimebecauseit’squitepuzzlingwhenyoufirstseeit.Whatdoesitmatch?Aspace,adash,andatilde?No,itmatchesarangeofcharactersfromthespaceuntilthetilde!
Toinvertthematch,place^asthefirstcharacterinthegroup:
/[^ -~]/
Thismatchestheoppositeof[ -~],thatis,allnonprintablecharacters.
8.10ExtracttextbetweentwoHTMLtags
m|<strong>([^<]*)</strong>|
BeforeIexplainthisregularexpression,letmesaythatit’sokaytomatchHTMLwithregularexpressionsonlyforquickhackswhenyouneedtogetthingsdoneandmoveon.YoushouldneveruseregularexpressionstomatchandparseHTMLinseriousapplicationsbecauseHTMLisactuallyacomplicatedlanguage,and,ingeneral,itcan’tbeparsedbyaregularexpression.Instead,usemoduleslikeHTML::TreeBuildertoaccomplishthetaskmorecleanly!
Thisregularexpressionsavestextbetweenthe<strong>...</strong>HTMLtagsinthe$1specialvariable.Thetrickiestpartofthisone-lineris([^<]*),whichmatcheseverythinguptothe<character.It’saregularexpressionidiom.
Forexample,iftheHTMLyou’retryingtomatchis<strong>hello</strong>,thenthisregularexpressioncaptureshellointhe$1variable.However,iftheHTMLyou’retryingtomatchis<strong><em>hello</em> </strong>,thenthisregularexpressiondoesn’tmatchatallbecausethereisanotherHTMLtagbetween<strong>and</strong>.
ToextracteverythingbetweentwoHTMLtags,includingotherHTMLtags,youcanwrite:
m|<strong>(.*?)</strong>|
m|<strong>(.*?)</strong>|
Thisregularexpressionsaveseverythingbetween<strong>...</strong>inthe$1variable.Forexample,iftheHTMLis<strong><em>hello</em></strong>,thisregularexpressionsets$1to<em>hello</em>.The(.*?)partoftheregularexpressionmatcheseverythingbetweenthetwonearest<strong>and</strong>tags.Thequestionmark?inthisregularexpressioncontrolsitsgreediness.
IfyouwanttobeagoodcitizenanduseHTML::TreeBuilder,thenaPerlprogramthatdoesthesamethingwouldlooklikethis:
use warnings;
use strict;
use HTML::TreeBuilder;
my $tree = HTML::TreeBuilder->new_from_content(
"<strong><em>hello</em></strong>"
);
my $strong = $tree->look_down(_tag => 'strong');
if ($strong) {
print $_->as_HTML for $strong->content_list;
}
$tree->delete;
Here,IcreatedanewHTML::TreeBuilderinstancefromthegivenstring;thenIfoundthe<strong>taganddumpedallthechildelementsofthe<strong>tagasHTML.Asyoucansee,althoughwritingaprogramlikethisisn’tsuitableasaone-liner,it’samuchmorerobustsolution.
8.11Replaceall<b>tagswith<strong>
$html =~ s|<(/)?b>|<$1strong>|g
Here,IassumethattheHTMLisinthevariable$html.Theexpression<(/)?b>matchestheopeningandclosing<b>tags,capturestheoptionalclosingtagslashinthegroup$1,andthenreplacesthematchedtagwitheither<strong>or</strong>,dependingonwhetheritfindsanopeningorclosingtag.
RememberthatthecorrectwaytodothisistouseHTML::TreeBuilderandwriteaproperprogram.Youshouldonlyusethisregularexpressionforaquickhack.Here’swhataprogramthatusesHTML::TreeBuilderlookslike:
use warnings;
use strict;
use HTML::TreeBuilder;
my $tree = HTML::TreeBuilder->new_from_content("
<div><p><b>section 1</b></p><p><b>section 2</b></p></div>
");
my @bs = $tree->look_down(_tag => 'b');
$_->tag('strong') for @bs;
print $tree->as_HTML;
$tree->delete;
Here,I’vecreatedtheHTML::TreeBuilderobjectfromthegivenstring;next,Ifoundallthe<b>tags,storedtheminthe@bsarray,andthenloopedoverall@bsandchangedtheirtagnameto<strong>.
8.12Extractallmatchesfromaregularexpression
my @matches = $text =~ /regex/g;
Here,theregularexpressionmatchisevaluatedinthelistcontext,whichmakesitreturnallmatches.Thematchesareputinthe@matchesvariable.
Forexample,thefollowingregularexpressionextractsallintegersfromastring:
my $t = "10 hello 25 moo 30 foo";
my @nums = $text =~ /\d+/g;
Afterexecutingthiscode,@numscontains(10, 25, 30).Youcanalsouseparenthesestocaptureonlypartofthestring.Forexample,here’showtocaptureonlythevaluesfromalinecontaininglotsofkey-valuepairs(suchaskey=value),separatedbysemicolons:
my @vals = $text =~ /[^=]+=([^;]+)/g;
Thisregularexpressionfirstmatchesthekeysthrough[^=]+,thenitmatchesthe=characterthatseparatesthekeysandvalues,andthenitmatchesthevalues([^;]+).Asyoucansee,thevaluepartoftheregularexpressioniswrappedinparenthesessothevaluesarecaptured.
Here’sanexample.Sayyouhaveafilewiththefollowingcontents:
access=all; users=peter,alastair,bill; languages=awk,sed,perl
andyouwritethisone-liner:
perl -nle 'my @vals = $_ =~ /[^=]+=([^;]+)/g; print "@vals"'
Runningitoutputsthefollowing:
all peter,alastair,bill awk,sed,perl
Thesearethevaluesfortheaccess,users,andlanguageskeys!
AppendixA.Perl’sSpecialVariables
Inthisappendix,IsummarizePerl’smostcommonlyusedspecial(predefined)variables,suchas$_,$.,$/,$\,$1,$2,$3(andsoon),$,,@F,and@ARGV,amongothers.
A.1Variable$_The$_variable,calledthedefaultvariable,isthemostcommonlyusedvariableinPerl.Oftenthisvariableispronounced“it”(whennotpronounced“dollar-underscore”);asyoureadon,you’llunderstandwhy.
Whenusingthe-nand-pcommand-linearguments,it’s(see?)wheretheinputisstored.Also,manyoperatorsandfunctionsactonitimplicitly.Here’sanexample:
perl -le '$_ = "foo"; print'
Here,Iplacethestring"foo"inthe$_variableandthencallprint.Whengivennoarguments,printprintsthecontentsofthe$_variable,whichis"foo".
Similarly,$_isusedbythes/regex/replace/and/regex/operatorswhenusedwithoutthe=~operator.Considerthisexample:
perl -ne '/foo/ && print'
Thisone-linerprintsonlylinesthatmatch/foo/.The/foo/operatorimplicitlyoperatesonthe$_variablethatcontainsthecurrentline.Youcouldrewritethisasfollows,butdoingsowouldrequiretoomuchtyping:
perl -ne 'if ($_ =~ /foo/) { print $_ }'
“Ifitmatches/foo/,printit”—yougettheidea.Youcouldalsoreplacetextinallthelinessimplybycallings/foo/bar/:
perl -pe 's/foo/bar/'
Interestingly,Perlborrowsthe$_variablefromsed.Rememberthatsedhasapatternspace?The$_variablecanalsobecalledPerl’spatternspace.Ifyouwrotethepreviousone-liner(perl -pe 's/foo/bar/')insed,itwouldlooklikesed 's/foo/bar/'becausesedputseachlineinthepatternspaceandthescommandactsonitimplicitly.Perlborrowsmanyconceptsandcommandsfromsed.
Using$_withthe-nargumentWhenusingthe-nargument,Perlputsthefollowinglooparoundyourprogram:
while (<>) {
# your program goes here (specified by -e)
}
Thewhile (<>)loopreadslinesfromstandardinputorfilesnamedonthecommandlineandputseachlineintothe$_variable.Youcanthenmodifythelinesandprintthem.Forexample,youcanreversethelines:
perl -lne 'print scalar reverse'
BecauseI’musingthe-nargumenthere,thisprogrambecomes
while (<>) {
print scalar reverse
}
whichisequivalentto
while (<>) {
print scalar reverse $_
}
}
ThetwoprogramsareequivalentbecausemanyPerlfunctionsacton$_implicitly,whichmakeswritingreverseandreverse $_functionallythesamething.Youneedscalartoputthereversefunctioninthescalarcontext.Otherwiseit’sinthelistcontext(printforcesthelistcontext)andwon’treversestrings.(Iexplainthe-nflagingreatdetailinone-liner2.6onpage12andlinereversinginone-liner6.22onpage67.)
Using$_withthe-pargumentWhenyouusethe-pargument,Perlputsthefollowinglooparoundyourprogram:
while (<>) {
# your program goes here (specified by -e)
} continue {
print or die "-p failed: $!\n";
}
Theresultisalmostthesameasforthe-nargument,exceptthataftereachiterationthecontentof$_isprinted(throughprintinthecontinueblock).
ToreversethelinesasIdidwith-n,Icandothis:
perl -pe '$_ = reverse $_'
Theprogramnowbecomes:
while (<>) {
$_ = reverse $_;
} continue {
print or die "-p failed: $!\n";
}
I’vemodifiedthe$_variableandsetittoreverse $_,whichreversestheline.Thecontinueblockmakessurethatit’sprinted.(One-liner2.1onpage7explainsthe-pargumentinmoredetail.)
Using$_explicitly
Using$_explicitlyThe$_variableisalsooftenusedexplicitly.Herearesomeexamplesofusingthe$_variableexplicitly:
perl -le '@vals = map { $_ * 2 } 1..10; print "@vals"'
Theoutputofthisone-lineris2 4 6 8 10 12 14 16 18 20.Here,Iusethemapfunctiontomapanexpressionovereachelementinthegivenlistandreturnanewlist,whereeachelementistheresultoftheexpression.Inthiscase,thelistis1..10(1 2 3 4 5 6 7 8 9 10)andtheexpressionis$_ * 2,whichmeansmultiplyeachelement(“it”)by2.Asyoucansee,I’musing$_explicitly.Whenthemapfunctioniteratesoverthelist,eachelementisputinto$_formyconvenience.
Nowlet’susemapinahandyone-liner.Howaboutonethatmultiplieseachelementonalineby2?
perl -alne 'print "@{[map { $_ * 2 } @F]}"'
Thisone-linermapstheexpression$_ * [email protected]"@{[...]}"isjustawaytoexecutecodeinsidequotes.(One-liner4.2onpage30explains@F,andone-liner4.4onpage32explains"@{[...]}".)
Anotherfunctionthatexplicitlyuses$_isgrep,whichletsyoufiltertheelementsfromalist.Here’sanexample:
perl -le '@vals = grep { $_ > 5 } 1..10; print "@vals"'
Theoutputofthisone-lineris6 7 8 9 10.Asyoucansee,grepfilteredelementsgreaterthan5fromthelist.Thecondition$_ > 5asks,“Isthecurrentelementgreaterthan5?”—or,moresuccinctly,“Isitgreaterthan5?”
Let’susegrepinaone-liner.Howaboutonethatfindsandprintsallelementsonthecurrentlinethatarepalindromes?
perl -alne 'print "@{[grep { $_ eq reverse $_ } @F]}"'
Theconditionspecifiedtothegrepfunctionhereis$_ eq reverse $_,whichasks,“Isthecurrentelementthesameasitsreverse?”Thisconditionistrueonlyforpalindromes.Forexample,giventhefollowinginput:
civic foo mom dad
bar baz 1234321 x
theone-lineroutputsthis:
civic mom dad
1234321 x
Asyoucansee,alloftheseelementsarepalindromes.
Youcanlearnevenmoreaboutthe$_variablebytypingperldoc perlvaratthecommandline.TheperlvardocumentationexplainsallthepredefinedvariablesinPerl.
A.2Variable$.Whenreadingafile,the$.variablealwayscontainsthelinenumberofthelinecurrentlybeingread.Forexample,thisone-linernumbersthelinesinfile:
perl -lne 'print "$. $_"' file
Youcandothesamethingwiththisone-liner,whichreplacesthecurrentlinewiththelinenumberfollowedbythesameline:
perl -pe '$_ = "$. $_"' file
The$.variableisn’tresetacrossfiles,sotonumbermultiplefilessimultaneously,youwrite
perl -pe '$_ = "$. $_"' file1 file2
Thisone-linercontinuesnumberinglinesinfile2wherefile1leftoff.(Iffile1contains10lines,thefirstlineoffile2isnumbered11.)
Toresetthe$.variable,youuseanexplicitcloseonthecurrentfilehandleARGV:
perl -pe '$_ = "$. $_"; close ARGV if eof' file1 file2
ARGVisaspecialfilehandlethatcontainsthecurrentlyopenfile.Bycallingeof,I’mcheckingtoseeifit’stheendofthecurrentfile.Ifso,closeclosesit,whichresetsthe$.variable.
YoucanchangewhatPerlconsiderstobealinebymodifyingthe$/variable.Thenextsectiondiscussesthisvariable.
A.3Variable$/The$/variableistheinputrecordseparator,whichisanewlinebydefault.ThisvariabletellsPerlwhattoconsideraline.Sayyouhavethissimpleprogramthatnumberslines:
perl -lne 'print "$. $_"' file
Because$/isanewlinebydefault,Perlreadseverythinguptothefirstnewline,putsitinthe$_variable,andincrementsthe$.variable.Next,itcallsprint"$. $_",whichprintsthecurrentlinenumberandtheline.Butifyouchangethevalueof$/totwonewlines,like$/ = "\n\n",Perlreadseverythinguptothefirsttwonewlines;thatis,itreadstextparagraphbyparagraphratherthanlinebyline.
Here’sanotherexample.Ifyouhaveafilelikethefollowing,youcanset$/to:,andPerlwillreadthefiledigitbydigit.
3:9:0:7:1:2:4:3:8:4:1:0:0:1:... (goes on and on)
Orifyouset$/toundef,Perlreadstheentirefileinasingleread(calledslurping):
perl -le '$/ = undef; open $f, "<", "file"; $contents = <$f>"
Thisone-linerslurpstheentirefilefileinvariable$contents.
Youcanalsoset$/toreferenceaninteger:
$/ = \1024
Inthiscase,Perlreadsthefile1024bytesatatime.(Thisisalsocalledrecord-by-recordreading.)
Youcanalsousethe-0command-lineswitchtoprovidethisvariablewithavalue,butnotethatyoucan’tdotherecord-by-recordversionlikethis.Forexample,toset$/to:,specify-0072because072istheoctalvalueofthe:character.
Torememberwhatthisvariabledoes,recallthatwhenquotingpoetry,linesareseparatedby/.
A.4Variable$\Thedollar-backslashvariableisappendedaftereveryprintoperation.Forexample,youcouldappendadotfollowedbyaspace". "aftereachprint:
perl -e '$\ = ". "; print "hello"; print "world"'
Thisone-linerproducesthefollowingoutput:
hello. world.
Modifyingthisvariableisespeciallyhelpfulwhenyouwanttoseparateprintoutsbydoublenewlines.
Torememberthisvariable,justrecallthatyouprobablywanttoprint\naftereveryline.NotethatforPerl5.10andlater,thefunctionsayisavailable,whichislikeprint,exceptthatitalwaysaddsanewlineattheendanddoesn’tusethe$\variable.
A.5Variables$1,$2,$3,andsoon
Variables$1,$2,$3,andsooncontainthematchesfromthecorrespondingsetofcapturingparenthesesinthelastpatternmatch.Here’sanexample:
perl -nle 'if (/She said: (.*)/) { print $1 }'
Thisone-linermatcheslinesthatcontainthestringShe said:andthencaptureseverythingafterthestringinvariable$1andprintsit.
Whenyouuseanotherpairofparentheses,thetextiscapturedinvariable$2,andsoon:
perl -nle 'if (/(She|He) said: (.*)/) { print "$1: $2" }'
Inthisone-liner,firsteither"She"or"He"iscapturedinvariable$1andthenanythingsheorhesaidiscapturedinvariable$2andprintedas"$1: $2".You’llgetthesamenumberofcapturevariablesasyouhavepairsofparentheses.
Toavoidcapturingtextinavariable,usethe?:symbolsinsidetheopeningparenthesis.Forexample,changing(She|He)to(?:She|He):
perl -nle 'if (/(?:She|He) said: (.*)/) { print "Someone said: $1" }'
willnotcapture"She"or"He"invariable$1.Instead,thesecondpairofparenthesescaptureswhatsheorhesaidinvariable$1.
BeginningwithPerl5.10,youcanusenamedcapturegroupsasin(?<name>...).Whenyoudo,insteadofusingvariables$1,$2,andsoon,youcanuse$+{name}torefertothegroup.Forexample,thiscaptures"She"or"He"inthenamedgroupgenderandthesaidtextinthenamedgrouptext:
perl -nle 'if (/(?<gender>She|He) said: (?<text>.*)/) {
print "$+{gender}: $+{text}"
}'
A.6Variable$,The$,variableistheoutputfieldseparatorforprintwhenprintingmultiple
values.It’sundefinedbydefault,whichmeansthatallitemsprintedareconcatenatedtogether.Indeed,ifyoudothis:
perl -le 'print 1, 2, 3'
youget123printedout.Ifyouset$,toacolon,however:
perl -le '$,=":"; print 1, 2, 3'
youget1:2:3.
Now,supposeyouwanttoprintanarrayofvalues.Ifyoudothis:
perl -le '@data=(1,2,3); print @data'
theoutputis123.Butifyouquotethevariable,thevaluesarespaceseparated:
perl -le '@data=(1,2,3); print "@data"'
Sotheoutputis1 2 3becausethearrayisinterpolatedinadouble-quotedstring.
A.7Variable$”Thisbringsustothe$"variable:asinglewhitespace(bydefault)that’sinsertedbetweeneveryarrayvaluewhenit’sinterpolated.Whenyouwritethingslikeprint "@data",the@dataarraygetsinterpolated,andthevalueof$"isinsertedbetweeneveryarrayelement.Forexample,thisprints1 2 3:
perl -le '@data=(1,2,3); print "@data"'
Butifyouchange$"to,say,adash-,theoutputbecomes1-2-3:
perl -le '@data=(1,2,3); $" = "-"; print "@data"'
Recallthe@{[...]}trickhere.Ifyouprint "@{[...]}",youcanexecutecodeplacedbetweenthesquarebrackets.Forexamplesandmoredetails,see
sectionA.1Variable$_’sdiscussionofthe$_variableonpage95andone-liner4.4onpage32.
A.8Variable@FThe@FvariableiscreatedinyourPerlprogramwhenyouusethe-aargument,whichstandsforauto-splitfields.Whenyouuse-a,theinputissplitonwhitespacecharactersandtheresultingfieldsareputin@F.Forexample,iftheinputlineisfoo bar baz,then@Fisanarray("foo", "bar", "baz").
Thistechniqueallowsyoutooperateonindividualfields.Forinstance,youcanaccess$F[2]toprintthethirdfieldasfollows(rememberingthatarraysstartfromindex0):
perl -ane 'print $F[2]'
Youcanalsoperformvariouscalculations,likemultiplyingthefifthfieldby2:
perl -ane '$F[4] *= 2; print "@F"'
Here,thefifthfield$F[4]ismultipliedby2,andprint "@F"printsallthefields,separatedbyaspace.
Youcanalsousethe-aargumentwiththe-Fargument,whichspecifiesthecharactertospliton.Forexample,toprocessthecolon-separatedentriesin/etc/passwdentries,youwrite
perl -a -F: -ne 'print $F[0]' /etc/passwd
whichprintstheusernamesfrom/etc/passwd.
A.9Variable@ARGVThe@ARGVvariablecontainstheargumentsthatyoupasstoyourPerlprogram.Forexample,thisprintsfoo bar baz:
perl -le 'print "@ARGV"' foo bar baz
Whenyouuse-nor-pflags,theargumentsthatyoupasstoyourPerlprogramareopenedonebyoneasfilesandremovedfrom@ARGV.Toaccessthefilenamespassedtoyourprogram,savetheminanewvariableintheBEGINblock:
perl -nle 'BEGIN { @A = @ARGV }; ...' file1 file2
Nowyoucanuse@Ainyourprogram,whichcontains("file1", "file2").Ifyoudidn’tdothisandyouused@ARGV,itwouldcontain("file2")atfirst,butwhenfile1wasprocessed,itwouldbeempty().Becarefulhere!
Asimilar-lookingvariable,$ARGV,containsthefilenameofthefilecurrentlybeingread,whichis"-"iftheprogramiscurrentlyreadingfromthestandardinput.
A.10Variable%ENVThe%ENVhashcontainsenvironmentvariablesfromyourshell.ThisvariablecomesinhandywhenyouwishtopredefinesomevaluesinyourscriptandthenusethesevaluesinyourPerlprogramorone-liner.
Sayyouwanttousethesystemfunctiontoexecuteaprogramthat’snotinthepath.Youcouldmodifythe$ENV{PATH}variableandappendtheneededpath:
perl -nle '
BEGIN { $ENV{PATH} .= ":/usr/local/yourprog/bin" }
...
system("yourprog ...");
'
Thisone-linerprintsallenvironmentvariablesfromPerl:
perl -le 'print "$_: $ENV{$_}" for keys %ENV'
Itloopsoverthekeys(environmentvariablenames)ofthe%ENVhash,putseachkeyintothe$_variable,andthenprintsthenamefollowedby$ENV{$_},whichisthevalueoftheenvironmentvariable.
AppendixB.UsingPerlOne-LinersOnWindows
Inthisappendix,I’llshowyouhowtorunPerlonWindows,installabashportonWindows,andusePerlone-linersinthreedifferentways:fromtheWindowsbashport,theWindowscommandprompt(cmd.exe),andPowerShell.
B.1PerlonWindowsBeforeyoucanrunPerlonWindows,youneedtoinstallPerlforWindows.MyfavoriteWindowsPerlportisStrawberryPerl(http://strawberryperl.com/),aPerlenvironmentwitheverythingyouneedtorunanddevelopPerlapplicationsonWindows.StrawberryPerlisdesignedtofunctionasmuchaspossiblelikethePerlenvironmentonUNIXsystems.ItincludesPerlbinaries,thegcccompilerandrelatedbuildtools,andmanyexternallibraries.
ToinstallStrawberryPerl,downloadandruntheinstaller,clickthroughabunchofmenusafewtimes,andyou’redone.Mychoicefortheinstallationdirectoryisc:\strawberryperl.(InstallinganyUNIXsoftwareforWindowsinadirectorywithnospacesinitisalwaysagoodidea.)Oncetheinstallationisdone,theinstallershouldputtheinstallationdirectoryinyourpathenvironmentvariablesoyoucanrunPerlfromthecommandlinerightaway.
Unfortunately,theWindowscommandlineisreallybasiccomparedtothecommandlineonUNIXsystems.AUNIXsystemrunsarealshellwithwell-definedcommand-lineparsingrules,butWindowsdoesn’treallyhaveanythinglikethat.TheWindowscommandlinehasweirdrulesabouthowittreatscertainsymbols,thequotingrulesaren’twelldefined,andtheescapingrulesarestrange,allofwhichmakesitdifficulttorunPerlone-liners.Therefore,thepreferredwaytorunone-linersonWindowsistouseaUNIXshell(suchasbash)forWindows,asyou’lllearninthenextsection.
B.2BashonWindowsGettingabashshelltorunonWindowsissimple.Irecommendwin-bash(http://win-bash.sourceforge.net/),astand-alonebashportforWindowsthatdoesn’tneedaspecialenvironmentoradditionalDLLs.Thedownloadisasinglezipfilethatcontainsthebashshell(bash.exe)andabunchofUNIXutilities(suchasawk,cat,cp,diff,find,grep,sed,vi,wc,andabout100others).
Toinstallbashandalltheutilities,simplyunzipthefileandyou’redone.Mychoicefortheinstallationdirectoryisc:\winbash,againwithnospacesinthedirectory.Runbash.exefromc:\winbashtostartthebashshell.
Ifyoustartbash.exeafteryouinstallStrawberryPerl,PerlshouldbeavailableforuserightawaybecausetheStrawberryPerlinstallershouldhaveupdatedthepathwiththeinstallationdirectory.Toconfirm,runperl --version.ItshouldoutputtheversionoftheinstalledPerl.Ifyougetanerrorsayingthatperlwasnotfound,manuallyappendtheC:\strawberryperl\perl\bindirectorytothePATHenvironmentvariablebyenteringthisinthecommandline:
PATH=$PATH:C:\\strawberryperl\\perl\\bin
BashusesthePATHvariabletofindexecutablestorun.ByappendingStrawberryPerl’sbinarydirectorytothePATHvariable,youtellbashwheretolookfortheperlexecutable.
B.3PerlOne-LinersinWindowsBashTherearesomeimportantdifferencesbetweenbashonWindowsandUNIX.Thefirstdifferencepertainstofilepaths.Win-bashsupportsbothUNIX-styleandWindows-stylepaths.
Sayyouinstallwin-bashinC:\winbash.Whenyoustartbash.exe,itshouldmaptherootdirectory/tothecurrentC:drive.Tochangetherootdirectorytoanotherdrive,suchasD:,entercd d:inthebashshell.TochangebacktoC:,entercd c:intheshell.NowyoucanaccessafilesuchasC:\work\report.txtvia/work/report.txt,c:/work/report.txt,orc:\\work\\report.txt.
Thebestthingaboutusingwin-bashisthatalloftheone-linersinthisbook
shouldworkbecauseyou’rerunningarealshelljustlikeinaUNIXenvironment!Forexample,tonumberthelinesintheC:\work\report.txtfile(one-liner3.1onpage17),youcanrun:
perl -pe '$_ = "$. $_"' C:/work/report.txt
OryoucanrefertothefileasifyouwereinUNIX:
perl -pe '$_ = "$. $_"' /work/report.txt
OryoucanuseWindows-stylepaths:
perl -pe '$_ = "$. $_"' C:\\work\\report.txt
Toavoidusingdoublebackslashes,youcansingle-quotethefilepath:
perl -pe '$_ = "$. $_"' 'C:\work\report.txt'
Ifthefilenamehasspacesinit,thenyoualwayshavetoquoteit.Forexample,toworkwithC:\DocumentsandSettings\Peter\MyDocuments\report.txt,quotetheentirepathwhenpassingittoaone-liner:
perl -pe '$_ = "$. $_"' 'C:\Documents and Settings\Peter\My Documents\report.txt'
OrusetheUNIX-stylepathtothefile:
perl -pe '$_ = "$. $_"' '/Documents and Settings/Peter/My Documents/report.txt'
QuotingthefilenameisnecessaryherebecausewithoutitPerlthinksyou’repassingitabunchoffilesratherthanasinglefilewithspacesinit.
B.4PerlOne-LinersintheWindowsCommandPromptIf,forsomereason,youcan’tusewin-bashasrecommended,youcanrunone-linersthroughtheWindowscommandprompt(cmd.exe).Youwillneedto
changetheone-linersinthisbookabitifyou’rerunningthemintheWindowscommandpromptbecauseofthewayWindowsparsesandtreatsthecommand-linearguments.Here’swhattodo.
First,verifythatPerlisavailablefromthecommandprompt.Startcmd.exeandenterperl --versioninthecommandline.IfyoudothisafterhavinginstalledStrawberryPerl,thecommandshouldoutputthePerlversion,andyou’regoodtogo.Otherwise,you’llhavetoupdatethePATHenvironmentvariablewiththepathtoStrawberryPerl’sbinarydirectory:
set PATH=%PATH%;C:\strawberryperl\perl\bin
AsinUNIX,thePATHvariabletellsthecommandpromptwheretolookforexecutables.
ConvertingOne-LinersintheWindowsCommandPromptNowlet’sseehowtoconvertone-linersforthecommandprompt,beginningwithone-liner2.1(page7),whichdouble-spacesafile.InUNIX,yousimplyrun:
perl -pe '$\ = "\n"' file
Ifyou’rerunningthisone-linerintheWindowscommandprompt,however,youhavetomakesurethatit’salwayswrappedindoublequotesfromtheoutsideandthatyou’veescapedanydoublequotesandspecialcharactersinsideit.Withthosechanges,theone-linerlookslikethisonWindows:
perl -pe "$\ = \"\n\"" file
Thisone-linerisgettinguglyquickly,butyoucanemployacoupleofPerltrickstomakeitlookalittlenicer.First,replacedoublequotesinsidetheone-linerwiththeqq/.../operator,whichdouble-quotesanythingbetweentheslashes.Writingqq/text/inPerlisthesameaswriting"text".Nowyourewritethisone-linerlikethis:
perl -pe "$\ = qq/\n/" file
That’salittlenicer.Youcanalsochangethecharacterthattheqqoperatorusestoseparateitscontent.Forexample,thesyntaxqq|...|double-quotesanythingbetweenthepipes:
perl -pe "$\ = qq|\n|" file
Youcouldevenusematchingparenthesesorcurlybrackets,likethis:
perl -pe "$\ = qq(\n)" file
orthis:
perl -pe "$\ = qq{\n}" file
Let’sseehowtoconvertseveralmoreone-linerstoWindows.HowaboutconvertinganIPaddresstoaninteger(one-liner4.27onpage45)?InUNIXyourun:
perl -MSocket -le 'print unpack("N", inet_aton("127.0.0.1"))'
OnWindows,youneedtochangethequotesoutsidetheone-linertodoublequotesandescapethedoublequotesinsidetheone-liner:
perl -MSocket -le "print unpack(\"N\", inet_aton(\"127.0.0.1\"))"
Oryoucanusetheqq|...|operatortoavoidescapingdoublequotesinsidetheone-liner:
perl -MSocket -le "print unpack(qq|N|, inet_aton(qq|127.0.0.1|))"
Forthingsthatdon’tneedinterpolation,suchastheformatstringNandtheIPaddress127.0.0.1,youcanalsousesinglequotesinsteadofdoublequotes:
perl -MSocket -le "print unpack('N', inet_aton('127.0.0.1'))"
Anothertrickistousetheq/.../operator,whichsingle-quotesanytextbetweentheslashes:
perl -MSocket -le "print unpack(q/N/, inet_aton(q/127.0.0.1/))"
Writingq/N/andq/127.0.0.1/isthesameaswriting'N'and'127.0.0.1'.
Let’sconvertanotherone-linerfromUNIXtoWindows.I’veexpandedittomultiplelinesforclarity:
perl -le '
$ip="127.0.0.1";
$ip =~ s/(\d+)\.?/sprintf("%02x", $1)/ge;
print hex($ip)
'
Unfortunately,toconvertthistoWindows,youhavetojoinallofthelinestogether(makingtheresultlessreadable),andapplythenewquotingrules:
perl -le "$ip=\"127.0.0.1\"; $ip =~ s/(\d+)\.?/sprintf(\"%02x\", $1)/ge; print
hex($ip)"
Youcanincreasethereadabilityalittlebyusingtheqqoperator:
perl -le "$ip=qq|127.0.0.1|; $ip =~ s/(\d+)\.?/sprintf(qq|%02x|, $1)/ge; print
hex($ip)"
orbyusingsinglequotes:
perl -le "$ip='127.0.0.1'; $ip =~ s/(\d+)\.?/sprintf('%02x', $1)/ge; print hex($ip)"
SymbolChallengesYoumightalsorunintoissueswiththecaret(^)symbolinone-linersbecausetheWindowscommandpromptusesthecaretastheescapesymbol.TotellWindowstotreatthecaretsymbolliterally,youusuallyhavetoreplaceeachcaretwithtwocarets:^^.
Let’slookatseveralexamplesthatsimplytrytoprintthe^character.Here’smyfirstattempt:
perl -e "print \"^\""
Nooutput!The^symboldisappeared.Let’stry^twice:
perl -e "print \"^^\""
Thisworked!Itprintedthe^symbol.Nowlet’stryusingsinglequotes:
perl -e "print '^'"
Thisalsoworkedandprinted^,andIdidn’tneedtoenter^twice.Usingqq/^/alsoworks:
perl -e "print qq/^/"
Asyoucansee,runningone-linersonWindowscanbetrickybecausetherearenouniformparsingrulesforthecommand-linearguments.Youmayrunintosimilarissueswhenwritingone-linerswiththe%,&,<,>,and|symbols.Ifso,tryprecedingthemwiththe^escapecharactersothat%becomes^%,&becomes^&,<becomes^<,>becomes^>,and|becomes^|.Ortrywrappingthemintheqqoperator,asIdiscussedpreviously.(Betteryet,installwin-bashandusetheone-linersthroughittoavoidalltheseissues.)
WindowsFilePathsWhenusingtheWindowscommandprompt,youcanpassfilenamestoone-linersinseveraldifferentways.Forexample,toaccessthefileC:\work\wrong-spacing.txt,youcanenter:
perl -pe "$\ = qq{\n}" C:\work\wrong-spacing.txt
Oryoucanreversetheslashes:
perl -pe "$\ = qq{\n}" C:/work/wrong-spacing.txt
Ifthefilenamecontainsspaces,youhavetoquotethepath:
perl -pe "$\ = qq{\n}" "C:\Documents and Settings\wrong-spacing.txt"
FormoreWindowsPerlusagehints,seetheWin32Perldocumentationathttp://perldoc.perl.org/perlwin32.html.
B.5PerlOne-LinersinPowerShellRunningone-linersinPowerShellisabitdifferentthanrunningtheminthecommandprompt(cmd.exe).ThemaindifferenceisthatPowerShellisamodernshellimplementationwithdifferentparsingrulesthanthecommandprompt.Inthissection,I’llshowyouhowtorunPerlone-linersinPowerShell.
First,youneedtoverifythatPerlworksinthePowerShellenvironment.Runperl --versioninthePowerShell.IfthecommandoutputsthePerlversion,thenPerlisavailable,andyoushouldbeabletoruntheone-liners.Otherwise,updatethePathenvironmentvariableandappendStrawberryPerl’sbinarydirectorytoitbyrunningthefollowingcommandinPowerShell:
$env:Path += ";C:\strawberryperl\perl\bin"
ThePathvariabletellsPowerShellwheretolookforexecutables,sowhenyourunperl,itsearchesallthedirectories(separatedbythe;character)forperl.exe.
ConvertingOne-LinersinPowerShellConsiderone-liner2.1(page7),whichdouble-spacesafile.InUNIX,theone-linerlookslikethis:
perl -pe '$\ = "\n"' file
Tomakethisone-linerworkinPowerShell,youhavetochangethreethings:
Escapethe$symbol,whichPowerShellusesforvariables,byaddingthe`character(backtick)beforeit:`$.
Aswiththecmd.execommandprompt,makesuredoublequotesareusedontheoutsideoftheone-liner.
Usetheqq/.../operatorforthedoublequotesinsidetheone-liner,asexplainedin“ConvertingOne-LinersintheWindowsCommandPrompt”onpage108.Youcan’tjustescapethedoublequoteswithabackslashaswiththecommandprompt,however;youmustusetheqq/.../operator.
Whenyouputitalltogether,thePowerShellversionofthisone-linerbecomes:
perl -pe "`$\ = qq/\n/" file
Tospecifyfullpathstofiles,useWindows-stylepaths.Forexample,toreferenceafileatC:\work\wrong-spacing.txt,enterthatpathdirectlyaftertheone-liner:
perl -pe "`$\ = qq/\n/" C:\work\wrong-spacing.txt
Ifthefilenameorfilepathcontainsspaces,enteritlikethis,withdoublequotesaroundit:
perl -pe "`$\ = qq/\n/" "C:\Documents and Settings\wrong-spacing.txt"
Nowforanotherversionofthesameone-liner.InUNIXtheone-linerlookslikethis:
perl -pe '$_ .= "\n" unless /^$/' file
ButinPowerShellyouhavetochangetheoutersinglequotestodoublequotes,escapethe$symbol,andchangedoublequotestoqq/.../insidetheone-liner:
perl -pe "`$_ .= qq/\n/ unless /^`$/" file
Nowlet’slookattheone-linerthatnumbersthenon-emptylinesinafile(one-liner3.2onpage18):
perl -pe '$_ = ++$x." $_" if /./'
WhenconvertedtoPowerShell,theone-linerlookslikethis:
perl -pe "`$_ = ++`$a.qq/ `$_/ if /./"
perl -pe "`$_ = ++`$a.qq/ `$_/ if /./"
Howabouttheartisticone-linerthatchecksifanumberisprime(one-liner4.1onpage29)?
perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'
InPowerShell,theone-linerlookslikethis:
perl -lne "(1x`$_) !~ /^1?`$|^(11+?)\1+`$/ && print qq/`$_ is prime/"
Remembertheone-lineronpage46thatconvertsIPstointegers?Here’showitlooksinUNIX:
perl -le '
$ip="127.0.0.1";
$ip =~ s/(\d+)\.?/sprintf("%02x", $1)/ge;
print hex($ip)
'
Andhere’sthesameone-linerforPowerShell:
perl -le "
`$ip=qq|127.0.0.1|;
`$ip =~ s/(\d+)\.?/sprintf(qq|%02x|, `$1)/ge;
print hex(`$ip)
"
One-LinersinPowerShell3.0+Ifyou’rerunningPowerShellversion3.0orlater,youcanusethe--%escapesequencetopreventPowerShellfromdoinganyadditionalparsing.
TofindoutwhichPowerShellversionyou’rerunning,enter$PSVersionTable.PSVersionintheshell.Itshouldoutputatablelikethis:
PS C:\Users\Administrator> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
3 0 -1 -1
Thistableshowsthatyou’rerunningPowerShellversion3.0,whichhasthe--%escapesequence.(OlderversionsofPowerShelldon’thavethissequence,inwhichcaseyouhavetousethetricksIdescribedearlier.)
Whenusingthe--%escapesequence,youdon’thavetoescapethe$symbol.Italsoletsyouescapethedoublequoteswithbackslashesinsidetheone-liner.Forexample,here’showtheone-linerthatdouble-spaceslineslookswiththe--%escapesequence:
perl --% -pe "$\ = \"\n\""
Youcanalsousetheqq/.../operatortoavoidescapingdoublequotesinsidetheone-liner:
perl --% -pe "$\ = qq/\n/"
Here’showyoucanwritetheotherversionofthesameone-linerinPowerShell3.0andlater:
perl --% -pe "$_ .= \"\n\" unless /^$/" file
Andthisishowtheone-linerthatnumbersthelineslooks:
perl --% -pe "$_ = ++$a.qq/ $_/ if /./"
Here’stheone-linerthatusesaregularexpressiontoseeifanumberisprime:
perl --% -lne "(1x$_) !~ /^1?$|^(11+?)\1+$/ && print \"$_ is prime\""
Andhere’stheone-linerthatconvertsIPstointegers:
perl --% -le "
$ip=\"127.0.0.1\";
$ip =~ s/(\d+)\.?/sprintf(\"%02x\", $1)/ge;
print hex($ip)
"
Asyoucansee,runningone-linersinPowerShellisquitetrickyandrequiresseveralworkarounds.Again,Irecommendthatyouinstallwin-bashasdescribed
severalworkarounds.Again,Irecommendthatyouinstallwin-bashasdescribedin“BashonWindows”onpage106toavoidhavingtoimplementtheseworkarounds.
AppendixC.Perl1Line.Txt
AsIwaswritingthisbook,Icompiledalltheone-linersinafilecalledperl1line.txt.Thisappendixisthatfile.Itcomesinveryhandywhenyouneedtoquicklylookupaone-liner.Youcanjustopenperl1line.txtinatexteditorandsearchfortheactionyouwanttoperform.Thelatestversionofthisfilecanalwaysbefoundathttp://www.catonmat.net/download/perl1line.txt.
C.1Spacing
Double-spaceafile
perl -pe '$\ = "\n"'
perl -pe 'BEGIN { $\ = "\n" }'
perl -pe '$_ .= "\n"'
perl -pe 's/$/\n/'
perl -nE 'say'
Double-spaceafile,excludingtheblanklines
perl -pe '$_ .= "\n" unless /^$/'
perl -pe '$_ .= "\n" if /\S/'
Triple-spaceafile
perl -pe '$\ = "\n\n"'
perl -pe '$_ .= "\n\n"'
perl -pe 's/$/\n\n/'
N-spaceafile
perl -pe '$_ .= "\n"x7'
Addablanklinebeforeeveryline
Addablanklinebeforeeveryline
perl -pe 's/^/\n/'
Removeallblanklines
perl -ne 'print unless /^$/'
perl -lne 'print if length'
perl -ne 'print if /\S/'
Removeallconsecutiveblanklines,leavingonlyone
perl -00 -pe ''
perl -00pe0
Compress/expandallblanklinesintoNconsecutivelines
perl -00 -pe '$_ .= "\n"x2'
Double-spacebetweenallwords
perl -pe 's/ / /g'
Removeallspacingbetweenwords
perl -pe 's/ +//g'
perl -pe 's/\s+//g'
Changeallspacingbetweenwordstoonespace
perl -pe 's/ +/ /g'
Insertaspacebetweenallcharacters
perl -lpe 's// /g'
C.2Numbering
Numberalllinesinafile
Numberalllinesinafile
perl -pe '$_ = "$. $_"'
perl -ne 'print "$. $_"'
Numberonlynon-emptylinesinafile
perl -pe '$_ = ++$x." $_" if /./'
perl -pe '$_ = ++$x." $_" if /\S/'
Numberandprintonlynon-emptylinesinafile(dropemptylines)
perl -ne 'print ++$x." $_" if /./'
Numberalllinesbutprintlinenumbersonlyfornon-emptylines
perl -pe '$_ = "$. $_" if /./'
Numberonlylinesthatmatchapattern;printothersunmodified
perl -pe '$_ = ++$x." $_" if /regex/'
Numberandprintonlylinesthatmatchapattern
perl -ne 'print ++$x." $_" if /regex/'
Numberalllinesbutprintlinenumbersonlyforlinesthatmatchapattern
perl -pe '$_ = "$. $_" if /regex/'
Numberalllinesinafileusingacustomformat
perl -ne 'printf "%-5d %s", $., $_'
Printthetotalnumberoflinesinafile(emulatewc-l)
perl -lne 'END { print $. }'
perl -le 'print $n = () = <>'
perl -le 'print $n = (() = <>)'
perl -le 'print scalar(() = <>)'
perl -le 'print scalar(() = <>)'
perl -le 'print scalar(@foo = <>)'
perl -ne '}{print $.'
Printthenumberofnon-emptylinesinafile
perl -le 'print scalar(grep { /./ } <>)'
perl -le 'print ~~grep{/./}<>'
perl -le 'print~~grep/./,<>'
perl -lE 'say~~grep/./,<>'
Printthenumberofemptylinesinafile
perl -lne '$x++ if /^$/; END { print $x+0 }'
perl -lne '$x++ if /^$/; END { print int $x }'
perl -le 'print scalar(grep { /^$/ } <>)'
perl -le 'print ~~grep{ /^$/ } <>'
Printthenumberoflinesinafilethatmatchapattern(emulategrep-c)
perl -lne '$x++ if /regex/; END { print $x+0 }'
Numberwordsacrossalllines
perl -pe 's/(\w+)/++$i.".$1"/ge'
Numberwordsoneachindividualline
perl -pe '$i=0; s/(\w+)/++$i.".$1"/ge'
Replaceallwordswiththeirnumericpositions
perl -pe 's/(\w+)/++$i/ge'
C.3Calculations
Checkifanumberisaprime
perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'
perl -lne '(1x$_) !~ /^1?$|^(11+?)\1+$/ && print "$_ is prime"'
Printthesumofallfieldsoneachline
perl -MList::Util=sum -alne 'print sum @F'
perl -MList::Util=sum -F: -alne 'print sum @F'
Printthesumofallfieldsonalllines
perl -MList::Util=sum -alne 'push @S,@F; END { print sum @S }'
perl -MList::Util=sum -alne '$s += sum @F; END { print $s }'
Shuffleallfieldsoneachline
perl -MList::Util=shuffle -alne 'print "@{[shuffle @F]}"'
perl -MList::Util=shuffle -alne 'print join " ", shuffle @F'
Findthenumericallysmallestelement(minimumelement)oneachline
perl -MList::Util=min -alne 'print min @F'
Findthenumericallysmallestelement(minimumelement)overalllines
perl -MList::Util=min -alne '@M = (@M, @F); END { print min @M }'
perl -MList::Util=min -alne '
$min = min @F;
$rmin = $min unless defined $rmin && $min > $rmin;
END { print $rmin }
'
perl -MList::Util=min -alne '$min = min($min // (), @F); END { print $min }'
Findthenumericallylargestelement(maximumelement)oneachline
perl -MList::Util=max -alne 'print max @F'
Findthenumericallylargestelement(maximumelement)overalllines
perl -MList::Util=max -alne '@M = (@M, @F); END { print max @M }'
perl -MList::Util=max -alne '
$max = max @F;
$rmax = $max unless defined $rmax && $max < $rmax;
END { print $rmax }
'
perl -MList::Util=max -alne '$max = max($max // (), @F); END { print $max }'
Replaceeachfieldwithitsabsolutevalue
perl -alne 'print "@{[map { abs } @F]}"'
Printthetotalnumberoffieldsoneachline
perl -alne 'print scalar @F'
Printthetotalnumberoffieldsoneachline,followedbytheline
perl -alne 'print scalar @F, " $_"'
Printthetotalnumberoffieldsonalllines
perl -alne '$t += @F; END { print $t }'
Printthetotalnumberoffieldsthatmatchapattern
perl -alne 'map { /regex/ && $t++ } @F; END { print $t || 0 }'
perl -alne '$t += /regex/ for @F; END { print $t }'
perl -alne '$t += grep /regex/, @F; END { print $t }'
Printthetotalnumberoflinesthatmatchapattern
perl -lne '/regex/ && $t++; END { print $t || 0 }'
Printthenumberπ
perl -Mbignum=bpi -le 'print bpi(21)'
perl -Mbignum=PI -le 'print PI'
Printthenumbere
perl -Mbignum=bexp -le 'print bexp(1,21)'
perl -Mbignum=e -le 'print e'
PrintUNIXtime(secondssinceJanuary1,1970,00:00:00UTC)
perl -le 'print time'
PrintGreenwichMeanTimeandlocalcomputertime
perl -le 'print scalar gmtime'
perl -le 'print scalar localtime'
Printyesterday’sdate
perl -MPOSIX -le '
@now = localtime;
$now[3] -= 1;
print scalar localtime mktime @now
'
Printthedate14months,9days,and7secondsago
perl -MPOSIX -le '
@now = localtime;
$now[0] -= 7;
$now[3] -= 9;
$now[4] -= 14;
print scalar localtime mktime @now
'
Calculatethefactorial
perl -MMath::BigInt -le 'print Math::BigInt->new(5)->bfac()'
perl -le '$f = 1; $f *= $_ for 1..5; print $f'
Calculatethegreatestcommondivisor
perl -MMath::BigInt=bgcd -le 'print bgcd(@list_of_numbers)'
perl -MMath::BigInt=bgcd -le 'print bgcd(20,60,30)'
perl -MMath::BigInt=bgcd -anle 'print bgcd(@F)'
perl -le '
$n = 20; $m = 35;
($m,$n) = ($n,$m%$n) while $n;
($m,$n) = ($n,$m%$n) while $n;
print $m
'
Calculatetheleastcommonmultiple
perl -MMath::BigInt=blcm -le 'print blcm(35,20,8)'
perl -MMath::BigInt=blcm -anle 'print blcm(@F)'
perl -le '
$a = $n = 20;
$b = $m = 35;
($m,$n) = ($n,$m%$n) while $n;
print $a*$b/$m
'
Generate10randomnumbersbetween5and15(excluding15)
perl -le 'print join ",", map { int(rand(15-5))+5 } 1..10'
perl -le '
$n=10;
$min=5;
$max=15;
$, = " ";
print map { int(rand($max-$min))+$min } 1..$n;
'
Generateallpermutationsofalist
perl -MAlgorithm::Permute -le '
$l = [1,2,3,4,5];
$p = Algorithm::Permute->new($l);
print "@r" while @r = $p->next
'
perl -MAlgorithm::Permute -le '
@l = (1,2,3,4,5);
Algorithm::Permute::permute { print "@l" } @l
'
Generatethepowerset
perl -MList::PowerSet=powerset -le '
@l = (1,2,3,4,5);
print "@$_" for @{powerset(@l)}
'
'
ConvertanIPaddresstoanunsignedinteger
perl -le '
$i=3;
$u += ($_<<8*$i--) for "127.0.0.1" =~ /(\d+)/g;
print $u
'
perl -le '
$ip="127.0.0.1";
$ip =~ s/(\d+)\.?/sprintf("%02x", $1)/ge;
print hex($ip)
'
perl -le 'print unpack("N", 127.0.0.1)'
perl -MSocket -le 'print unpack("N", inet_aton("127.0.0.1"))'
ConvertanunsignedintegertoanIPaddress
perl -MSocket -le 'print inet_ntoa(pack("N", 2130706433))'
perl -le '
$ip = 2130706433;
print join ".", map { (($ip>>8*($_))&0xFF) } reverse 0..3
'
perl -le '
$ip = 2130706433;
$, = ".";
print map { (($ip>>8*($_))&0xFF) } reverse 0..3
'
perl -le '
$ip = 2130706433;
$, = ".";
print map { (($ip>>8*($_))&0xFF) } 3,2,1,0
'
C.4WorkingwithArraysandStrings
Generateandprintthealphabet
perl -le 'print a..z'
perl -le 'print ("a".."z")'
perl -le '$, = ","; print ("a".."z")'
perl -le '$alphabet = join ",", ("a".."z"); print $alphabet'
Generateandprintallthestringsfrom“a”to“zz”
perl -le 'print join ",", ("a".."zz")'
perl -le 'print join ",", "aa".."zz"'
Createahexlookuptable
@hex = (0..9, "a".."f")
perl -le '
$num = 255;
@hex = (0..9, "a".."f");
while ($num) {
$s = $hex[($num % 16)].$s;
$num = int $num/16;
}
print $s
'
perl -le 'printf("%x", 255)'
perl -le '$num = "ff"; print hex $num'
Generatearandomeight-characterpassword
perl -le 'print map { ("a".."z")[rand 26] } 1..8'
perl -le 'print map { ("a".."z", 0..9)[rand 36] } 1..8'
Createastringofspecificlength
perl -le 'print "a"x50'
perl -e 'print "a"x1024'
perl -le '@list = (1,2)x20; print "@list"'
Createanarrayfromastring
@months = split ' ', "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec"
@months = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/
Createastringfromthecommand-linearguments
perl -le 'print "(", (join ",", @ARGV), ")"' val1 val2 val3
perl -le '
print "INSERT INTO table VALUES (", (join ",", @ARGV), ")"
' val1 val2 val3
Findthenumericvaluesforcharactersinastring
perl -le 'print join ", ", map { ord } split //, "hello world"'
perl -le 'print join ", ", unpack("C*", "hello world")'
perl -le '
print join ", ", map { sprintf "0x%x", ord $_ } split //, "hello world"
'
perl -le '
print join ", ", map { sprintf "%o", ord $_ } split //, "hello world"
'
perl -le '
print join ", ", map { sprintf "%#o", ord $_ } split //, "hello world"
'
ConvertalistofnumericASCIIvaluesintoastring
perl -le '
@ascii = (99, 111, 100, 105, 110, 103);
print pack("C*", @ascii)
'
perl -le '
@ascii = (99, 111, 100, 105, 110, 103);
$str = join "", map chr, @ascii;
print $str
'
perl -le 'print map chr, 99, 111, 100, 105, 110, 103'
perl -le 'print map chr, @ARGV' 99 111 100 105 110 103
Generateanarraywithoddnumbersfrom1to100
perl -le '@odd = grep {$_ % 2 == 1} 1..100; print "@odd"'
perl -le '@odd = grep { $_ & 1 } 1..100; print "@odd"'
Generateanarraywithevennumbersfrom1to100
perl -le '@even = grep {$_ % 2 == 0} 1..100; print "@even"'
Findthelengthofastring
perl -le 'print length "one-liners are great"'
Findthenumberofelementsinanarray
perl -le '@array = ("a".."z"); print scalar @array'
perl -le '@array = ("a".."z"); print $#array + 1'
perl -le 'print scalar @ARGV' *.txt
perl -le 'print scalar (@ARGV=<*.txt>)'
C.5TextConversionandSubstitution
ROT13astring
perl -le '$str = "bananas"; $str =~ y/A-Za-z/N-ZA-Mn-za-m/; print $str'
perl -lpe 'y/A-Za-z/N-ZA-Mn-za-m/' file
perl -pi.bak -e 'y/A-Za-z/N-ZA-Mn-za-m/' file
Base64-encodeastring
perl -MMIME::Base64 -e 'print encode_base64("string")'
perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' file
Base64-decodeastring
perl -MMIME::Base64 -le 'print decode_base64("base64string")'
perl -MMIME::Base64 -0777 -ne 'print decode_base64($_)' file
URL-escapeastring
perl -MURI::Escape -le 'print uri_escape("http://example.com")'
URL-unescapeastring
perl -MURI::Escape -le 'print uri_unescape("http%3A%2F%2Fexample.com")'
HTML-encodeastring
perl -MHTML::Entities -le 'print encode_entities("<html>")'
HTML-decodeastring
perl -MHTML::Entities -le 'print decode_entities("<html>")'
Convertalltexttouppercase
perl -nle 'print uc'
perl -ple '$_ = uc'
perl -nle 'print "\U$_"'
Convertalltexttolowercase
perl -nle 'print lc'
perl -nle 'print "\L$_"'
Uppercaseonlythefirstletterofeachline
perl -nle 'print ucfirst lc'
perl -nle 'print "\u\L$_"'
Invertthelettercase
perl -ple 'y/A-Za-z/a-zA-Z/'
Title-caseeachline
perl -ple 's/(\w+)/\u$1/g'
Stripleadingwhitespace(spaces,tabs)fromthebeginningofeachline
perl -ple 's/^[ \t]+//'
perl -ple 's/^\s+//'
Striptrailingwhitespace(spaces,tabs)fromtheendofeachline
perl -ple 's/[ \t]+$//'
perl -ple 's/\s+$//'
Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
perl -ple 's/^[ \t]+|[ \t]+$//g'
perl -ple 's/^\s+|\s+$//g'
ConvertUNIXnewlinestoDOS/Windowsnewlines
perl -pe 's|\012|\015\012|'
ConvertDOS/WindowsnewlinestoUNIXnewlines
perl -pe 's|\015\012|\012|'
ConvertUNIXnewlinestoMacnewlines
perl -pe 's|\012|\015|'
Substitute(findandreplace)“foo”with“bar”oneachline
perl -pe 's/foo/bar/'
perl -pe 's/foo/bar/g'
Substitute(findandreplace)“foo”with“bar”onlinesthatmatch“baz”
perl -pe '/baz/ && s/foo/bar/'
perl -pe 's/foo/bar/ if /baz/'
Printparagraphsinreverseorder
perl -00 -e 'print reverse <>' file
Printalllinesinreverseorder
perl -lne 'print scalar reverse $_'
perl -lne 'print scalar reverse'
perl -lpe '$_ = reverse $_'
perl -lpe '$_ = reverse'
Printcolumnsinreverseorder
perl -alne 'print "@{[reverse @F]}"'
perl -F: -alne 'print "@{[reverse @F]}"'
perl -F: -alne '$" = ":"; print "@{[reverse @F]}"'
perl -F: -alne '$" = ":"; print "@{[reverse @F]}"'
C.6SelectivelyPrintingandDeletingLines
Printthefirstlineofafile(emulatehead-1)
perl -ne 'print; exit' file
perl -i -ne 'print; exit' file
perl -i.bak -ne 'print; exit' file
Printthefirst10linesofafile(emulatehead-10)
perl -ne 'print if $. <= 10' file
perl -ne '$. <= 10 && print' file
perl -ne 'print if 1..10' file
perl -ne 'print; exit if $. == 10' file
Printthelastlineofafile(emulatetail-1)
perl -ne '$last = $_; END { print $last }' file
perl -ne 'print if eof' file
Printthelast10linesofafile(emulatetail-10)
perl -ne 'push @a, $_; @a = @a[@a-10..$#a] if @a>10; END { print @a }' file
perl -ne 'push @a, $_; shift @a if @a>10; END { print @a }' file
Printonlylinesthatmatcharegularexpression
perl -ne '/regex/ && print'
perl -ne 'print if /regex/'
Printonlylinesthatdonotmatcharegularexpression
perl -ne '!/regex/ && print'
perl -ne 'print if !/regex/'
perl -ne 'print unless /regex/'
perl -ne '/regex/ || print'
Printeverylineprecedingalinethatmatchesaregularexpression
perl -ne '/regex/ && $last && print $last; $last = $_'
Printeverylinefollowingalinethatmatchesaregularexpression
perl -ne 'if ($p) { print; $p = 0 } $p++ if /regex/'
perl -ne '$p && print && ($p = 0); $p++ if /regex/'
perl -ne '$p && print; $p = /regex/'
PrintlinesthatmatchregularexpressionsAAAandBBBinanyorder
perl -ne '/AAA/ && /BBB/ && print'
Printlinesthatdon’tmatchregularexpressionsAAAandBBB
perl -ne '!/AAA/ && !/BBB/ && print'
PrintlinesthatmatchregularexpressionAAAfollowedbyBBBfollowedbyCCC
perl -ne '/AAA.*BBB.*CCC/ && print'
Printlinesthatareatleast80characterslong
perl -ne 'print if length >= 80'
perl -lne 'print if length >= 80'
Printlinesthatarefewerthan80characterslong
perl -ne 'print if length() < 80'
Printonlyline13
perl -ne '$. == 13 && print && exit'
Printalllinesexceptline27
perl -ne '$. != 27 && print'
perl -ne 'print if $. != 27'
perl -ne 'print unless $. == 27'
perl -ne 'print unless $. == 27'
Printonlylines13,19,and67
perl -ne 'print if $. == 13 || $. == 19 || $. == 67'
perl -ne '
@lines = (13, 19, 88, 290, 999, 1400, 2000);
print if grep { $_ == $. } @lines
'
Printalllinesfrom17to30
perl -ne 'print if $. >= 17 && $. <= 30'
perl -ne 'print if 17..30'
Printalllinesbetweentworegularexpressions(includingthelinesthatmatch)
perl -ne 'print if /regex1/../regex2/'
Printthelongestline
perl -ne '
$l = $_ if length($_) > length($l);
END { print $l }
'
Printtheshortestline
perl -ne '
$s = $_ if $. == 1;
$s = $_ if length($_) < length($s);
END { print $s }
'
Printalllinescontainingdigits
perl -ne 'print if /\d/'
Printalllinescontainingonlydigits
perl -ne 'print if /^\d+$/'
perl -ne 'print if /^\d+$/'
perl -lne 'print unless /\D/'
Printalllinescontainingonlyalphabeticcharacters
perl -ne 'print if /^[[:alpha:]]+$/
Printeverysecondline
perl -ne 'print if $. % 2'
Printeverysecondline,beginningwiththesecondline
perl -ne 'print if $. % 2 == 0'
perl -ne 'print unless $. % 2'
Printallrepeatedlinesonlyonce
perl -ne 'print if ++$a{$_} == 2'
Printalluniquelines
perl -ne 'print unless $a{$_}++'
C.7UsefulRegularExpressions
MatchsomethingthatlookslikeanIPaddress
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
/^(\d{1,3}\.){3}\d{1,3}$/
perl -ne 'print if /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/'
Testwhetheranumberisintherange0to255
/^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/
perl -le '
map { $n++ if /^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/ } 0..255;
END { print $n }
'
perl -le '
perl -le '
map { $n++ if /^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/ } 0..1000;
END { print $n }
'
MatchanIPaddress
my $ip_part = qr/[0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]/;
if ($ip =~ /^$ip_part\.$ip_part\.$ip_part\.$ip_part$/) {
print "valid ip\n";
}
if ($ip =~ /^($ip_part\.){3}$ip_part$/) {
print "valid ip\n";
}
perl -ne '
$ip_part = qr|([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|;
print if /^($ip_part\.){3}$ip_part$/
'
Checkwhetherastringlookslikeanemailaddress
/\S+@\S+\.\S+/
use Email::Valid;
print Email::Valid->address('[email protected]') ? 'valid email' : 'invalid email';
perl -MEmail::Valid -ne 'print if Email::Valid->address($_)'
Checkwhetherastringisanumber
/^\d+$/
/^[+-]?\d+$/
/^[+-]?\d+\.?\d*$/
perl -MRegexp::Common -ne 'print if /$RE{num}{real}/'
perl -MRegexp::Common -ne 'print if /$RE{num}{hex}/'
perl -MRegexp::Common -ne 'print if /$RE{num}{oct}/'
perl -MRegexp::Common -ne 'print if /$RE{num}{bin}/'
Checkwhetherawordappearsinastringtwice
/(word).*\1/
Increaseallintegersinastringbyone
$str =~ s/(\d+)/$1+1/ge
perl -MRegexp::Common -pe 's/($RE{num}{real})/$1+1/ge'
perl -MRegexp::Common -pe 's/($RE{num}{real})/$1+1/ge'
ExtracttheHTTPUser-AgentstringfromHTTPheaders
/^User-Agent: (.+)$/
MatchprintableASCIIcharacters
/[ -~]/
ExtracttextbetweentwoHTMLtags
m|<strong>([^<]*)</strong>|
m|<strong>(.*?)</strong>|
Replaceall<b>tagswith<strong>
$html =~ s|<(/)?b>|<$1strong>|g
Extractallmatchesfromaregularexpression
my @matches = $text =~ /regex/g;
Index
ANOTEONTHEDIGITALINDEX
Alinkinanindexentryisdisplayedasthesectiontitleinwhichthatentryappears.Becausesomesectionshavemultipleindexmarkers,itisnotunusualforanentrytohaveseverallinkstothesamesection.Clickingonanylinkwilltakeyoudirectlytotheplaceinthetextinwhichthemarkerappears.
Symbols
!operator,7.6Printonlylinesthatdonotmatcharegularexpression
!~operator,4.1Checkifanumberisaprime
$,(fieldseparator)variable,4.3Printthesumofallfieldsonalllines,A.5Variables$1,$2,$3,andsoon
$.variable,3.1Numberalllinesinafile,Using$_explicitly
$/variable,A.2Variable$.
$1,$2,$3,…variables,3.13Numberwordsacrossalllines,A.4Variable$\
$variable+0construct,3.10Printthenumberofnon-emptylinesinafile
$variable=()=<>construct,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
$variable||0construct,4.13Printthetotalnumberoffieldsthatmatchapattern
$\variable,2.1Double-spaceafile,A.4Variable$\
$_variable,2.1Double-spaceafile,6.22Printalllinesinreverseorder,Perl’sSpecialVariables
$”variable,6.23Printcolumnsinreverseorder,A.5Variables$1,$2,$3,andsoon
%ENVvariable,A.9Variable@ARGV
-0command-lineargument,2.6Removeallblanklines,A.2Variable$.
-00command-lineargument,2.6Removeallblanklines,6.19Substitute(findandreplace)“foo”with“bar”oneachline
-0777command-lineargument,6.1ROT13astring
-acommand-lineargument,4.1Checkifanumberisaprime,A.7Variable$”
-ecommand-lineargument,IntroductiontoPerlOne-Liners,2.1Double-spaceafile
-Ecommand-lineargument,2.1Double-spaceafile
-Fcommand-lineargument,4.2Printthesumofallfieldsoneachline,6.23Printcolumnsinreverseorder
-icommand-lineargument,IntroductiontoPerlOne-Liners,6.1ROT13astring,7.1Printthefirstlineofafile(emulatehead-1)
-i.bakcommand-lineargument,IntroductiontoPerlOne-Liners,6.1ROT13astring,7.1Printthefirstlineofafile(emulatehead-1)
-lcommand-lineargument,IntroductiontoPerlOne-Liners,2.6Removeallblanklines
-Mcommand-lineargument,4.1Checkifanumberisaprime
-Mmodule=arg,4.2Printthesumofallfieldsoneachline
-ncommand-lineargument,IntroductiontoPerlOne-Liners,2.4N-spaceafile,A.1Variable$_
-pcommand-lineargument,IntroductiontoPerlOne-Liners,2.1Double-spaceafile,Using$_withthe-nargument
.operator,2.1Double-spaceafile
..(range)operator,WorkingWithArraysandStrings,7.2Printthefirst10linesofafile(emulatehead-10),7.17Printalllinesfrom17to30
//operator,4.6Findthenumericallysmallestelement(minimumelement)overalllines
/etc/passwd,IntroductiontoPerlOne-Liners,A.7Variable$”
<>(diamond)operator,2.6Removeallblanklines,3.9Printthetotalnumberoflinesinafile(emulatewc-l),5.13Findthenumberofelementsinanarray,6.19Substitute(findandreplace)“foo”with“bar”oneachline
=~operator,4.1Checkifanumberisaprime
@ARGVarray,5.6Createanarrayfromastring,5.6Createanarrayfromastring,A.7Variable$”,A.7Variable$”
@array1=(@array1,@array2)construct,4.4Shuffleallfieldsoneachline
@Farray,4.1Checkifanumberisaprime,4.1Checkifanumberisaprime,4.9Replaceeachfieldwithitsabsolutevalue,4.9Replaceeachfieldwithitsabsolutevalue,A.7Variable$”,A.7Variable$”
@TimToady(LarryWall),2.6Removeallblanklines
@{[…]}construct,4.3Printthesumofallfieldsonalllines
\Eescapesequence,6.6HTML-encodeastring,6.9Convertalltexttolowercase
\Lescapesequence,6.9Convertalltexttolowercase
\Uescapesequence,6.6HTML-encodeastring
\uescapesequence,6.9Convertalltexttolowercase
||(logicalOR)operator,4.6Findthenumericallysmallestelement(minimumelement)overalllines
}{(eskimooperator)construct,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
~~(doublebitwisenegate)construct,3.9Printthetotalnumberoflinesinafile(emulatewc-l),3.10Printthenumberofnon-emptylinesinafile
πconstant,4.15Printthenumberπ,4.15Printthenumberπ
“actionifcondition”statement,3.1Numberalllinesinafile,3.4Numberalllinesbutprintlinenumbersonlyfornon-emptylines
“actionunlesscondition”statement,2.2Double-spaceafile,excludingtheblanklines
A
Abigail,Calculations
abs(absolutevalue)function,4.9Replaceeachfieldwithitsabsolutevalue
adding
blanklines,Spacing
fields(calculatingsumof),IntroductiontoPerlOne-Liners,4.1Checkifanumberisaprime
spaces,betweencharacters,2.11Changeallspacingbetweenwordstoonespace
addresses
email,matchinglookalikeswithregularexpressions,8.3MatchanIPaddress
IP
convertingunsignedintegers,toandfrom,4.26Generatethepowerset
lookalikes,matching,UsefulRegularExpressions
valid,matching,8.2Testwhetheranumberisintherange0to255
Algorithm::Permutemodule,4.24Generate10randomnumbersbetween5and15(excluding15)
alphabet,generating,WorkingWithArraysandStrings
arguments.(seecommand-linearguments)
ARGVfilehandle,Using$_explicitly
arrays.(seelists)
ASCII
characters,printable,findingwithregularexpressions,8.9MatchprintableASCIIcharacters
numericvalues,convertingintostrings,5.9ConvertalistofnumericASCIIvaluesintoastring
auto-splitting,4.1Checkifanumberisaprime,A.7Variable$”
B
backupfiles,IntroductiontoPerlOne-Liners
base64encoding,6.1ROT13astring
bash,onWindows,UsingPerlOne-LinersOnWindows
one-linersin,B.3PerlOne-LinersinWindowsBash
bash.exe(win-bash),UsingPerlOne-LinersOnWindows,B.3PerlOne-LinersinWindowsBash
BEGINblock,2.1Double-spaceafile
bignummodule,4.15Printthenumberπ
blanklines,addingorremoving,Spacing
blocks
BEGIN,2.1Double-spaceafile
END,3.8Numberalllinesinafileusingacustomformat
C
calculating
absolutevalue,4.9Replaceeachfieldwithitsabsolutevalue
array,numberofelementsin,5.10Generateanarraywithoddnumbersfrom1to100
econstant,4.15Printthenumberπ
factorials,4.19Printyesterday’sdate
greatestcommondivisor(gcd),4.21Calculatethefactorial
increasing,integersinastring,8.7Increaseallintegersinastringbyone
leastcommonmultiple(lcm),4.23Calculatetheleastcommonmultiple
maximumelement,4.6Findthenumericallysmallestelement(minimumelement)overalllines
minimumelement,4.4Shuffleallfieldsoneachline
number
ofelements,inanarray,5.10Generateanarraywithoddnumbersfrom1to100
offields,4.9Replaceeachfieldwithitsabsolutevalue
oflines,3.8Numberalllinesinafileusingacustomformat,4.13Printthetotalnumberoffieldsthatmatchapattern
numericpositions,ofwords,3.15Replaceallwordswiththeirnumericpositions
permutations,oflists,4.24Generate10randomnumbersbetween5and15(excluding15)
powerset,4.26Generatethepowerset
range,whetheranumberisin,8.1MatchsomethingthatlookslikeanIPaddress
sum,offields,IntroductiontoPerlOne-Liners,4.1Checkifanumberisaprime
πconstant,4.15Printthenumberπ
case,converting,6.6HTML-encodeastring
characters
ASCII,printable,8.9MatchprintableASCIIcharacters
caseof,6.6HTML-encodeastring
numericvaluesof,5.6Createanarrayfromastring
spacingof,2.11Changeallspacingbetweenwordstoonespace
chroperator,5.9ConvertalistofnumericASCIIvaluesintoastring
closefunction,Using$_explicitly
cmd.exe(Windowscommandprompt),B.4PerlOne-LinersintheWindowsCommandPrompt
columns
orderof,reversing,6.22Printalllinesinreverseorder
sumofelementsin,IntroductiontoPerlOne-Liners
commandprompt,Windows,B.4PerlOne-LinersintheWindowsCommandPrompt
command-linearguments
-0,2.6Removeallblanklines,A.2Variable$.
-00,2.6Removeallblanklines,6.19Substitute(findandreplace)“foo”with“bar”oneachline
-0777,6.1ROT13astring
-a,4.1Checkifanumberisaprime,A.7Variable$”
-e,IntroductiontoPerlOne-Liners,2.1Double-spaceafile
-E,2.1Double-spaceafile
-F,4.2Printthesumofallfieldsoneachline,6.23Printcolumnsinreverseorder
-i,IntroductiontoPerlOne-Liners,6.1ROT13astring,7.1Printthefirstlineofafile(emulatehead-1)
-i.bak,IntroductiontoPerlOne-Liners,6.1ROT13astring,7.1Printthefirstlineofafile(emulatehead-1)
-l,IntroductiontoPerlOne-Liners,2.6Removeallblanklines
-M,4.1Checkifanumberisaprime
-Mmodule=arg,4.2Printthesumofallfieldsoneachline
-n,IntroductiontoPerlOne-Liners,2.4N-spaceafile,A.1Variable$_
-p,IntroductiontoPerlOne-Liners,2.1Double-spaceafile,Using$_withthe-nargument
ComprehensivePerlArchiveNetwork(CPAN),IntroductiontoPerlOne-Liners
conditionalstatements(if,unless),2.2Double-spaceafile,excludingtheblanklines,3.1Numberalllinesinafile,3.4Numberalllinesbutprintlinenumbersonlyfornon-emptylines
constants
e,4.15Printthenumberπ
π,4.15Printthenumberπ
constructs
$variable+0construct,3.10Printthenumberofnon-emptylinesinafile
$variable=()=<>construct,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
$variable||0construct,4.13Printthetotalnumberoffieldsthatmatchapattern
@array1=(@array1,@array2)construct,4.4Shuffleallfieldsoneachline
@{[…]}construct,4.3Printthesumofallfieldsonalllines
}{(eskimooperator),3.9Printthetotalnumberoflinesinafile(emulatewc-l)
~~(doublebitwisenegate),3.9Printthetotalnumberoflinesinafile(emulatewc-l),3.10Printthenumberofnon-emptylinesinafile
converting
case,6.6HTML-encodeastring
IPaddresses,toandfromunsignedintegers,4.26Generatethepowerset
newlines,fordifferentoperatingsystems,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
numericASCIIvalues,intostrings,5.9ConvertalistofnumericASCIIvaluesintoastring
CPAN(ComprehensivePerlArchiveNetwork),IntroductiontoPerlOne-Liners
cpan(utility),6.9Convertalltexttolowercase,7.20Printtheshortestline
D
date,IntroductiontoPerlOne-Liners,4.18PrintGreenwichMeanTimeandlocalcomputertime,4.19Printyesterday’sdate
DeMorgan’slaw,7.6Printonlylinesthatdonotmatcharegularexpression
decoding
frombase64,6.2Base64-encodeastring
fromHTML,6.6HTML-encodeastring
URLs,6.2Base64-encodeastring
definedfunction,4.6Findthenumericallysmallestelement(minimumelement)overalllines
deleting
blanklines,2.4N-spaceafile
lines,byprintingothers,SelectivelyPrintingandDeletingLines
spacingbetweenwords,2.9Double-spacebetweenallwords
whitespace,6.13Stripleadingwhitespace(spaces,tabs)fromthebeginningofeachline
diamondoperator(<>),2.6Removeallblanklines,3.9Printthetotalnumberoflinesinafile(emulatewc-l),5.13Findthenumberofelementsinanarray,6.19Substitute(findandreplace)“foo”with“bar”oneachline
documentation
perldoc,IntroductiontoPerlOne-Liners
Win32Perl,SymbolChallenges
DOS/Windowsnewlines,converting,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
doublebitwisenegate~~construct,3.9Printthetotalnumberoflinesinafile(emulatewc-l),3.10Printthenumberofnon-emptylinesinafile
E
econstant,4.15Printthenumberπ,4.15Printthenumberπ
elements.,4.9Replaceeachfieldwithitsabsolutevalue
(seealsofields)
maximum,4.6Findthenumericallysmallestelement(minimumelement)overalllines
minimum,4.4Shuffleallfieldsoneachline
numberof,inanarray,5.10Generateanarraywithoddnumbersfrom1to100
emailaddresses,matchinglookalikeswithregularexpressions,8.3MatchanIPaddress
Email::Validmodule,8.4Checkwhetherastringlookslikeanemailaddress
emptylines,numberof,3.10Printthenumberofnon-emptylinesinafile
encoding
asbase64,6.1ROT13astring
asHTML,6.6HTML-encodeastring
URLs,6.2Base64-encodeastring
ENDblock,3.8Numberalllinesinafileusingacustomformat
eoffunction,7.2Printthefirst10linesofafile(emulatehead-10)
epoch,timesince,4.15Printthenumberπ
escapesequences
\E,6.6HTML-encodeastring,6.9Convertalltexttolowercase
\L,6.9Convertalltexttolowercase
\U,6.6HTML-encodeastring
\u,6.9Convertalltexttolowercase
escaping
characters,touseone-liners
inPowerShell,B.5PerlOne-LinersinPowerShell
inWindows,B.4PerlOne-LinersintheWindowsCommandPrompt
loops,withtheeskimooperator}{construct,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
URLs,6.2Base64-encodeastring
eskimooperator}{construct,3.9Printthetotalnumberoflinesinafile
(emulatewc-l)
Euclid’salgorithm,4.21Calculatethefactorial
exitfunction,7.1Printthefirstlineofafile(emulatehead-1)
F
factorials,calculating,4.19Printyesterday’sdate
fields.,3.13Numberwordsacrossalllines
(seealsowords)
absolutevalue,replacingwith,4.9Replaceeachfieldwithitsabsolutevalue
auto-splitting,4.1Checkifanumberisaprime
numberof,4.9Replaceeachfieldwithitsabsolutevalue
separator($,variable),4.3Printthesumofallfieldsonalllines,A.5Variables$1,$2,$3,andsoon
shuffling,4.3Printthesumofallfieldsonalllines
sumof,calculating,IntroductiontoPerlOne-Liners,4.1Checkifanumberisaprime
filepaths,inWindows,B.3PerlOne-LinersinWindowsBash,SymbolChallenges
filenameexpansion(globbing),5.13Findthenumberofelementsinanarray
files
backup,IntroductiontoPerlOne-Liners
numberoflinesin,3.8Numberalllinesinafileusingacustomformat
numberinglinesin,Numbering
printing,firstandlastlinesin,7.1Printthefirstlineofafile(emulatehead-1)
slurping,A.2Variable$.
spacing,Spacing
find-and-replace
HTMLtags,8.10ExtracttextbetweentwoHTMLtags
text,IntroductiontoPerlOne-Liners,6.19Substitute(findandreplace)“foo”with“bar”oneachline
flip-flopoperator,7.2Printthefirst10linesofafile(emulatehead-10),7.17Printalllinesfrom17to30
functions.,4.9Replaceeachfieldwithitsabsolutevalue
(seealsooperators)
abs,4.9Replaceeachfieldwithitsabsolutevalue
close,Using$_explicitly
defined,4.6Findthenumericallysmallestelement(minimumelement)overalllines
eof,7.2Printthefirst10linesofafile(emulatehead-10)
exit,7.1Printthefirstlineofafile(emulatehead-1)
gmtime,4.18PrintGreenwichMeanTimeandlocalcomputertime
grep,3.9Printthetotalnumberoflinesinafile(emulatewc-l),Using$_withthe-pargument
inet_aton,4.27ConvertanIPaddresstoanunsignedinteger
inet_ntoa,4.28ConvertanunsignedintegertoanIPaddress
join,4.4Shuffleallfieldsoneachline,5.1Generateandprintthealphabet
lc,6.6HTML-encodeastring
length,2.6Removeallblanklines,5.10Generateanarraywithoddnumbersfrom1to100
localtime,4.18PrintGreenwichMeanTimeandlocalcomputertime,4.19Printyesterday’sdate
map,4.9Replaceeachfieldwithitsabsolutevalue,Using$_withthe-pargument
mktime,4.19Printyesterday’sdate
pack,4.28ConvertanunsignedintegertoanIPaddress,5.9ConvertalistofnumericASCIIvaluesintoastring
printf,3.8Numberalllinesinafileusingacustomformat
push,4.2Printthesumofallfieldsoneachline
rand,4.23Calculatetheleastcommonmultiple,5.3Createahexlookuptable
sprintf,5.8Findthenumericvaluesforcharactersinastring
system,A.9Variable@ARGV
time,4.15Printthenumberπ
uc,6.6HTML-encodeastring
ucfirst,6.9Convertalltexttolowercase
unpack,4.27ConvertanIPaddresstoanunsignedinteger,5.8Findthenumericvaluesforcharactersinastring
G
gcd(greatestcommondivisor),4.21Calculatethefactorial
generating
alphabet,WorkingWithArraysandStrings
numbers
constants,4.15Printthenumberπ
even,5.10Generateanarraywithoddnumbersfrom1to100
odd,5.9ConvertalistofnumericASCIIvaluesintoastring
random,4.23Calculatetheleastcommonmultiple
passwords,5.3Createahexlookuptable
permutations,4.24Generate10randomnumbersbetween5and15(excluding15)
powerset,4.26Generatethepowerset
strings,from“a”to“zz”,5.1Generateandprintthealphabet
globbing(filenameexpansion),5.13Findthenumberofelementsinanarray
GMT(GreenwichMeanTime),4.18PrintGreenwichMeanTimeandlocalcomputertime
gmtimefunction,4.18PrintGreenwichMeanTimeandlocalcomputertime
golfing(Perl),3.9Printthetotalnumberoflinesinafile(emulatewc-l)
greatestcommondivisor(gcd),4.21Calculatethefactorial
GreenwichMeanTime(GMT),4.18PrintGreenwichMeanTimeandlocalcomputertime
grepfunction,3.9Printthetotalnumberoflinesinafile(emulatewc-l),Using$_withthe-pargument
H
hexlookuptable,5.3Createahexlookuptable
hexoperator,4.27ConvertanIPaddresstoanunsignedinteger,5.3Createahexlookuptable
HTML
encoding,6.6HTML-encodeastring
tags
extractingtextbetween,8.9MatchprintableASCIIcharacters
replacing,8.10ExtracttextbetweentwoHTMLtags
HTML::Entitiesmodule,6.6HTML-encodeastring
HTML::TreeBuildermodule,8.9MatchprintableASCIIcharacters
HTTPheaders,extractingUser-Agentstringfrom,8.7Increaseallintegersinastringbyone
I
I
ifstatement,3.1Numberalllinesinafile,3.4Numberalllinesbutprintlinenumbersonlyfornon-emptylines
inet_atonfunction,4.27ConvertanIPaddresstoanunsignedinteger
inet_ntoafunction,4.28ConvertanunsignedintegertoanIPaddress
initialcapitalization,6.9Convertalltexttolowercase
intoperator,3.10Printthenumberofnon-emptylinesinafile
integers
convertingIPaddresses,toandfrom,4.26Generatethepowerset
increasing,8.7Increaseallintegersinastringbyone
invertingcase,ofletters,6.9Convertalltexttolowercase
IPaddresses
converting
tounsignedintegers,4.26Generatethepowerset
unsignedintegersto,4.28ConvertanunsignedintegertoanIPaddress
matching
lookalikes,UsefulRegularExpressions
valid,8.2Testwhetheranumberisintherange0to255
iptables,IntroductiontoPerlOne-Liners
J
joinfunction,4.4Shuffleallfieldsoneachline,5.1Generateandprintthealphabet
L
lcfunction,6.6HTML-encodeastring
lcm(leastcommonmultiple),4.23Calculatetheleastcommonmultiple
leastcommonmultiple(lcm),4.23Calculatetheleastcommonmultiple
length
creatingstringsby,5.4Generatearandomeight-characterpassword
none,2.6Removeallblanklines
ofstrings,finding,5.10Generateanarraywithoddnumbersfrom1to100
printinglinesby,7.12Printlinesthatareatleast80characterslong,7.17Printalllinesfrom17to30
lengthfunction,2.6Removeallblanklines,5.10Generateanarraywithoddnumbersfrom1to100
letters.(seecharacters)
lines
blank,addingorremoving,2.4N-spaceafile
case,converting,6.6HTML-encodeastring
numberof
emptyornon-empty,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
inafile,total,3.8Numberalllinesinafileusingacustomformat
matchingapattern,4.13Printthetotalnumberoffieldsthatmatchapattern
numbering,Numbering
withtotalnumberofwordson,4.11Printthetotalnumberoffieldsoneachline,followedbytheline
wordson,3.13Numberwordsacrossalllines
order,reversing,6.22Printalllinesinreverseorder
printing
bycontents,7.20Printtheshortestline
bylength,7.12Printlinesthatareatleast80characterslong,7.17Printalllinesfrom17to30
bymatchingregularexpressions,3.10Printthenumberofnon-
emptylinesinafile,7.4Printthelast10linesofafile(emulatetail-10),7.17Printalllinesfrom17to30
bynumber,7.12Printlinesthatareatleast80characterslong
everysecond,7.22Printalllinescontainingonlydigits
firstandlast,7.1Printthefirstlineofafile(emulatehead-1)
repeatedorunique,7.25Printeverysecondline,beginningwiththesecondline
replacingtexton,6.19Substitute(findandreplace)“foo”with“bar”oneachline
spacing,Spacing
List::PowerSetmodule,4.26Generatethepowerset
List::Utilmodule,4.1Checkifanumberisaprime,4.3Printthesumofallfieldsonalllines
lists
convertingintostrings,5.9ConvertalistofnumericASCIIvaluesintoastring
creatingfromstrings,5.4Generatearandomeight-characterpassword
generating
alphabet,WorkingWithArraysandStrings
evennumbers,5.10Generateanarraywithoddnumbersfrom1to100
fromregularexpressionmatches,8.11Replaceall<b>tagswith<strong>
oddnumbers,5.9ConvertalistofnumericASCIIvaluesintoastring
numberofelementsin,5.10Generateanarraywithoddnumbersfrom1to100
permutationsof,4.24Generate10randomnumbersbetween5and15(excluding15)
powerset,4.26Generatethepowerset
slicing,4.18PrintGreenwichMeanTimeandlocalcomputertime
localtime,4.18PrintGreenwichMeanTimeandlocalcomputertime
localtimefunction,4.18PrintGreenwichMeanTimeandlocalcomputertime,4.19Printyesterday’sdate
logicalORoperator,4.6Findthenumericallysmallestelement(minimumelement)overalllines
lookuptable,hex,5.3Createahexlookuptable
lowercase,convertingto,6.6HTML-encodeastring
M
MacOSnewlines,convertingto,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
mapfunction,4.9Replaceeachfieldwithitsabsolutevalue,Using$_withthe-pargument
matching.(seeregularexpressions)
Math::BigIntmodule,4.19Printyesterday’sdate
maximumelement,calculating,4.6Findthenumericallysmallestelement(minimumelement)overalllines
MIME::Base64module,6.1ROT13astring
minimumelement,calculating,4.4Shuffleallfieldsoneachline
mktimefunction,4.19Printyesterday’sdate
modules
Algorithm::Permute,4.24Generate10randomnumbersbetween5and15(excluding15)
bignum,4.15Printthenumberπ
Email::Valid,8.4Checkwhetherastringlookslikeanemailaddress
HTML::Entities,6.6HTML-encodeastring
HTML::TreeBuilder,8.9MatchprintableASCIIcharacters
List::PowerSet,4.26Generatethepowerset
List::Util,4.1Checkifanumberisaprime,4.3Printthesumofallfieldsonalllines
Math::BigInt,4.19Printyesterday’sdate
MIME::Base64,6.1ROT13astring
POSIX,4.19Printyesterday’sdate
Regexp::Common,8.4Checkwhetherastringlookslikeanemailaddress
Socket,4.27ConvertanIPaddresstoanunsignedinteger
URI::Escape,6.2Base64-encodeastring
months,days,andsecondsago,4.19Printyesterday’sdate
N
newlines
adding,Spacing
convertingfordifferentoperatingsystems,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
non-emptylines
numberof,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
numbering,3.1Numberalllinesinafile
number
ofelements,inanarray,5.10Generateanarraywithoddnumbersfrom1to100
offields,4.9Replaceeachfieldwithitsabsolutevalue
oflines,3.8Numberalllinesinafileusingacustomformat,4.13Printthetotalnumberoffieldsthatmatchapattern
numbering
lines,Numbering,4.11Printthetotalnumberoffieldsoneachline,followedbytheline
words,3.13Numberwordsacrossalllines
numbers
constants,4.15Printthenumberπ
even,5.10Generateanarraywithoddnumbersfrom1to100
odd,5.9ConvertalistofnumericASCIIvaluesintoastring
random,4.23Calculatetheleastcommonmultiple
numeric
positions,ofwords,3.15Replaceallwordswiththeirnumericpositions
values,ofcharacters,5.6Createanarrayfromastring
O
one-linersinWindows
inbash,B.3PerlOne-LinersinWindowsBash
inPowerShell,SymbolChallenges
inWindowscommandprompt,B.4PerlOne-LinersintheWindowsCommandPrompt
operatingsystems.,B.4PerlOne-LinersintheWindowsCommandPrompt
(seealsoWindows)
newlines,convertingfor,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
operators.
!operator,7.6Printonlylinesthatdonotmatcharegularexpression
!~operator,4.1Checkifanumberisaprime
.operator,2.1Double-spaceafile
..(range),WorkingWithArraysandStrings,7.2Printthefirst10linesofafile(emulatehead-10),7.17Printalllinesfrom17to30
//operator,4.6Findthenumericallysmallestelement(minimumelement)overalllines
<>(diamond),2.6Removeallblanklines,3.9Printthetotalnumberoflinesinafile(emulatewc-l),5.13Findthenumberofelementsinanarray,6.19Substitute(findandreplace)“foo”with“bar”oneachline
=~operator,4.1Checkifanumberisaprime
chr,5.9ConvertalistofnumericASCIIvaluesintoastring
flip-flop,7.2Printthefirst10linesofafile(emulatehead-10),7.17Printalllinesfrom17to30
hex,4.27ConvertanIPaddresstoanunsignedinteger,5.3Createahexlookuptable
int,3.10Printthenumberofnon-emptylinesinafile
ord,5.6Createanarrayfromastring
q/…/,ConvertingOne-LinersintheWindowsCommandPrompt
qq/…/,B.4PerlOne-LinersintheWindowsCommandPrompt
qr/…/,8.2Testwhetheranumberisintherange0to255
qw/…/,5.6Createanarrayfromastring
reverse,6.22Printalllinesinreverseorder
s/regex/replace/,2.4N-spaceafile
say,2.1Double-spaceafile
scalar,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
shift,7.4Printthelast10linesofafile(emulatetail-10)
split,5.4Generatearandomeight-characterpassword
ternary,8.4Checkwhetherastringlookslikeanemailaddress
tr,TextConversionandSubstitution
x,2.4N-spaceafile,5.4Generatearandomeight-characterpassword
y,TextConversionandSubstitution
||(logicalOR),4.6Findthenumericallysmallestelement(minimumelement)overalllines
}{(eskimo),3.9Printthetotalnumberoflinesinafile(emulatewc-l)
ORoperator,logical,4.6Findthenumericallysmallestelement(minimumelement)overalllines
ordoperator,5.6Createanarrayfromastring
order,reversing,6.19Substitute(findandreplace)“foo”with“bar”oneachline
P
packfunction,4.28ConvertanunsignedintegertoanIPaddress,5.9ConvertalistofnumericASCIIvaluesintoastring
paragraphs
orderof,reversing,6.19Substitute(findandreplace)“foo”with“bar”oneachline
slurping,2.6Removeallblanklines
passwords,generatingrandom,5.3Createahexlookuptable
patterns.(seeregularexpressions)
Perl
golfing,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
onWindows.,UsingPerlOne-LinersOnWindows
(seealsoWindows)
Strawberry,UsingPerlOne-LinersOnWindows,B.4PerlOne-LinersintheWindowsCommandPrompt
versions,IntroductiontoPerlOne-Liners
perldoc,IntroductiontoPerlOne-Liners
permutations,oflists,4.24Generate10randomnumbersbetween5and15(excluding15)
POSIXmodule,4.19Printyesterday’sdate
powerset,generating,4.26Generatethepowerset
PowerShell,SymbolChallenges
prime,checkingifanumberis,Calculations
printffunction,3.8Numberalllinesinafileusingacustomformat
printing
fields,numberof,4.9Replaceeachfieldwithitsabsolutevalue
lines
bycontents,7.20Printtheshortestline
bylength,7.12Printlinesthatareatleast80characterslong,7.17Printalllinesfrom17to30
bymatchingregularexpressions,3.10Printthenumberofnon-emptylinesinafile,7.4Printthelast10linesofafile(emulatetail-10),7.17Printalllinesfrom17to30
bynumber,7.12Printlinesthatareatleast80characterslong
everysecond,7.22Printalllinescontainingonlydigits
firstandlast,7.1Printthefirstlineofafile(emulatehead-1)
non-empty,3.1Numberalllinesinafile
numberof,3.8Numberalllinesinafileusingacustomformat,4.13Printthetotalnumberoffieldsthatmatchapattern
repeatedorunique,7.25Printeverysecondline,beginningwiththesecondline
pushfunction,4.2Printthesumofallfieldsoneachline
Q
q/…/operator,ConvertingOne-LinersintheWindowsCommandPrompt
qq/…/operator,B.4PerlOne-LinersintheWindowsCommandPrompt
qr/…/operator,8.2Testwhetheranumberisintherange0to255
qw/…/operator,5.6Createanarrayfromastring
R
randfunction,4.23Calculatetheleastcommonmultiple,5.3Createahexlookuptable
random
numbers,generating,4.23Calculatetheleastcommonmultiple
passwords,generating,5.3Createahexlookuptable
rangeoperator,WorkingWithArraysandStrings,7.2Printthefirst10linesofafile(emulatehead-10)
range,calculatingwhetheranumberisin,8.1MatchsomethingthatlookslikeanIPaddress
Regexp::Commonmodule,8.4Checkwhetherastringlookslikeanemailaddress
regularexpressions
ASCIIcharacters,tomatchprintable,8.9MatchprintableASCIIcharacters
emailaddresses,tomatchlookalikes,8.3MatchanIPaddress
HTMLtags
toextracttextbetween,8.9MatchprintableASCIIcharacters
toreplace,8.10ExtracttextbetweentwoHTMLtags
IPaddresses,andlookalikes,tomatch,UsefulRegularExpressions
linesmatching
numberof,4.13Printthetotalnumberoffieldsthatmatchapattern
tonumberandprint,3.5Numberonlylinesthatmatchapattern;printothersunmodified
toprint,3.10Printthenumberofnon-emptylinesinafile,7.4Printthelast10linesofafile(emulatetail-10),7.17Printalllinesfrom17to30
listingallmatches,8.11Replaceall<b>tagswith<strong>
range,totestwhetheranumberisin,8.1MatchsomethingthatlookslikeanIPaddress
removing.(seedeleting)
repeated
lines,7.25Printeverysecondline,beginningwiththesecondline
words,8.5Checkwhetherastringisanumber
replacing
HTMLtags,8.10ExtracttextbetweentwoHTMLtags
text,IntroductiontoPerlOne-Liners,6.19Substitute(findandreplace)“foo”with“bar”oneachline
reverseoperator,6.22Printalllinesinreverseorder
ROT13,astring,TextConversionandSubstitution
S
s/regex/replace/operator,2.4N-spaceafile
sayoperator,2.1Double-spaceafile
scalaroperator,3.9Printthetotalnumberoflinesinafile(emulatewc-l)
shiftoperator,7.4Printthelast10linesofafile(emulatetail-10)
shufflingfields(words),4.3Printthesumofallfieldsonalllines
slicing,lists,4.18PrintGreenwichMeanTimeandlocalcomputertime
slurping,2.6Removeallblanklines,A.2Variable$.
Socketmodule,4.27ConvertanIPaddresstoanunsignedinteger
spacing
ofcharacters,2.11Changeallspacingbetweenwordstoonespace
oflines,Spacing
ofwords,2.9Double-spacebetweenallwords
splitoperator,5.4Generatearandomeight-characterpassword
splitting,auto-,4.1Checkifanumberisaprime,A.7Variable$”
sprintffunction,5.8Findthenumericvaluesforcharactersinastring
StrawberryPerl,UsingPerlOne-LinersOnWindows,B.4PerlOne-LinersintheWindowsCommandPrompt
strings
arrays,creatingfrom,5.4Generatearandomeight-characterpassword
base64encoding,6.1ROT13astring
case,converting,6.6HTML-encodeastring
characters,numericvaluesof,5.6Createanarrayfromastring
emailaddresses,andlookalikes,8.3MatchanIPaddress
generating
alphabet,WorkingWithArraysandStrings
bylength,5.4Generatearandomeight-characterpassword
fromASCIIvalues,5.9ConvertalistofnumericASCIIvaluesintoastring
fromcommand-linearguments,5.6Createanarrayfromastring
from“a”to“zz”,5.1Generateandprintthealphabet
passwords,random,5.3Createahexlookuptable
HTMLencoding,6.6HTML-encodeastring
integers,increasing,8.7Increaseallintegersinastringbyone
IPaddresses,andlookalikes,UsefulRegularExpressions
length,finding,5.10Generateanarraywithoddnumbersfrom1to100
numbers,checkingif,8.4Checkwhetherastringlookslikeanemailaddress
numericvalues,ofcharacters,5.6Createanarrayfromastring
order,reversing,6.19Substitute(findandreplace)“foo”with“bar”oneachline
ROT13,TextConversionandSubstitution
shufflingfields(words),4.3Printthesumofallfieldsonalllines
spacing,2.9Double-spacebetweenallwords
URLescaping,6.2Base64-encodeastring
withwordsappearingtwice,8.5Checkwhetherastringisanumber
strippingwhitespace,6.13Stripleadingwhitespace(spaces,tabs)fromthebeginningofeachline
substituting
HTMLtags,8.10ExtracttextbetweentwoHTMLtags
text,IntroductiontoPerlOne-Liners,6.19Substitute(findandreplace)“foo”with“bar”oneachline
sum(offields),calculating,IntroductiontoPerlOne-Liners,4.1Checkifanumberisaprime
systemfunction,A.9Variable@ARGV
T
ternaryoperator,8.4Checkwhetherastringlookslikeanemailaddress
text.(seefiles;lines;words)
There’sMoreThanOneWayToDoIt(TIMTOWTDI),2.6Removeallblanklines
time
date,IntroductiontoPerlOne-Liners,4.18PrintGreenwichMeanTimeandlocalcomputertime,4.19Printyesterday’sdate
GreenwichMeanTime(GMT),4.18PrintGreenwichMeanTimeandlocalcomputertime
local,4.18PrintGreenwichMeanTimeandlocalcomputertime
UNIX,4.15Printthenumberπ
timefunction,4.15Printthenumberπ
TIMTOWTDI(There’sMoreThanOneWayToDoIt),2.6Removeallblanklines
titlecase,convertingto,6.9Convertalltexttolowercase
troperator,TextConversionandSubstitution
U
ucfunction,6.6HTML-encodeastring
ucfirstfunction,6.9Convertalltexttolowercase
unescaping,URLs,6.2Base64-encodeastring
uniquelines,7.25Printeverysecondline,beginningwiththesecondline
UNIX
newlines,converting,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
time,4.15Printthenumberπ
unlessstatement,2.2Double-spaceafile,excludingtheblanklines
unpackfunction,4.27ConvertanIPaddresstoanunsignedinteger,5.8Findthenumericvaluesforcharactersinastring
unsignedintegers,convertingIPaddressestoandfrom,4.26Generatethepowerset
uppercase,convertingto,6.6HTML-encodeastring
URI::Escapemodule,6.2Base64-encodeastring
URL-escaping,6.2Base64-encodeastring
usernames,listingfrom/etc/passwd,IntroductiontoPerlOne-Liners,A.7Variable$”
V
v-string(versionstring)literal,6.13Stripleadingwhitespace(spaces,tabs)fromthebeginningofeachline
validIPaddresses,matching,8.2Testwhetheranumberisintherange0to255
values,ofcharacters,5.6Createanarrayfromastring
variables
$,(fieldseparator),4.3Printthesumofallfieldsonalllines,A.5Variables$1,$2,$3,andsoon
$.variable,3.1Numberalllinesinafile,Using$_explicitly
$/variable,A.2Variable$.
$1,$2,$3,…variables,3.13Numberwordsacrossalllines,A.4Variable$\
$\variable,2.1Double-spaceafile,A.4Variable$\
$_variable,2.1Double-spaceafile,6.22Printalllinesinreverseorder,Perl’sSpecialVariables
$”variable,6.23Printcolumnsinreverseorder,A.5Variables$1,$2,$3,andsoon
%ENV,A.9Variable@ARGV
@ARGV,5.6Createanarrayfromastring,A.7Variable$”
@F,4.1Checkifanumberisaprime,4.9Replaceeachfieldwithitsabsolutevalue,A.7Variable$”
W
Wall,Larry,2.6Removeallblanklines
whitespace,stripping,6.13Stripleadingwhitespace(spaces,tabs)fromthebeginningofeachline
win-bash(bash.exe),UsingPerlOne-LinersOnWindows,B.3PerlOne-LinersinWindowsBash
Windows
bashon,UsingPerlOne-LinersOnWindows
bash.exe(win-bash),UsingPerlOne-LinersOnWindows,B.3PerlOne-LinersinWindowsBash
cmd.exe,B.4PerlOne-LinersintheWindowsCommandPrompt
commandprompt,B.4PerlOne-LinersintheWindowsCommandPrompt
filepaths
bash,B.3PerlOne-LinersinWindowsBash
commandprompt,SymbolChallenges
PowerShell,B.5PerlOne-LinersinPowerShell
newlines,6.15Stripwhitespace(spaces,tabs)fromthebeginningandendofeachline
one-liners
inbash,B.3PerlOne-LinersinWindowsBash
inPowerShell,SymbolChallenges
inWindowscommandprompt,B.4PerlOne-LinersintheWindowsCommandPrompt
Perlon,UsingPerlOne-LinersOnWindows
StrawberryPerl,UsingPerlOne-LinersOnWindows
win-bash,UsingPerlOne-LinersOnWindows,B.3PerlOne-LinersinWindowsBash
words.,4.9Replaceeachfieldwithitsabsolutevalue
(seealsofields)
numberof,onaline,4.9Replaceeachfieldwithitsabsolutevalue
numbering,onaline,3.13Numberwordsacrossalllines
numericpositionsof,3.15Replaceallwordswiththeirnumericpositions
passwords,generatingrandom,5.3Createahexlookuptable
repeated,8.5Checkwhetherastringisanumber
shuffling,4.3Printthesumofallfieldsonalllines
spacingof,2.9Double-spacebetweenallwords
X
xoperator,2.4N-spaceafile,5.4Generatearandomeight-characterpassword
Y
yoperator,TextConversionandSubstitution
yesterday’sdate,4.19Printyesterday’sdate
AbouttheAuthorPeterisKruminsisaprogrammer,systemsadministrator,start-upmanager,andall-aroundhacker.HeisthecofounderofBrowserlingandTestling,andherunsthepopularprogrammingblogcatonmat.net.
PerlOne-Liners130ProgramsThatGetThingsDone
PeterisKruminsCopyright©2013Allrightsreserved.Nopartofthisworkmaybereproducedortransmittedinanyformorbyanymeans,electronicormechanical,includingphotocopying,recording,orbyanyinformationstorageorretrievalsystem,withoutthepriorwrittenpermissionofthecopyrightownerandthepublisher.
Publisher:WilliamPollockProductionEditor:RileyHoffmanCoverIllustration:TinaSalamehInteriorDesign:OctopodStudiosDevelopmentalEditor:WilliamPollockTechnicalReviewer:AlastairMcGowan-DouglasCopyeditor:LeeAnnPickrellCompositor:RileyHoffmanProofreader:ElaineMerrill
Forinformationondistribution,translations,orbulksales,pleasecontactNoStarchPress,Inc.directly:
LibraryofCongressCataloging-in-PublicationData
Krumins, Peteris.
Perl one-liners : 130 programs that get things done / by Peteris Krumins.
pages cm
Summary: "Snappy Perl programs to streamline tasks and sharpen coding skills"--
Provided by publisher.
ISBN 978-1-59327-520-4 (paperback) -- ISBN 1-59327-520-X (paperback)
1. Perl (Computer program language) I. Title.
QA76.73.P22K78 2013
005.13'3--dc23
2013030613
NoStarchPressandtheNoStarchPresslogoareregisteredtrademarksofNoStarchPress,Inc.Otherproductandcompanynamesmentionedhereinmaybethetrademarksoftheirrespectiveowners.Ratherthanuseatrademarksymbolwitheveryoccurrenceofatrademarkedname,weareusingthenamesonlyinaneditorialfashionandtothebenefitofthetrademarkowner,withnointentionofinfringementofthetrademark.
Theinformationinthisbookisdistributedonan“AsIs”basis,withoutwarranty.Whileeveryprecautionhasbeentakeninthepreparationofthiswork,neithertheauthornorNoStarchPress,Inc.shallhaveanyliabilitytoanypersonorentitywithrespecttoanylossordamagecausedorallegedtobecauseddirectlyorindirectlybytheinformationcontainedinit.
NoStarchPress
2013-12-20T11:08:53-08:00