Regular Expression Perl/Oneliners

From Teknologisk videncenter
Jump to: navigation, search

Capture

Eksempel 1

my $txt ="4-11-2009";
my @array;
$txt =~ /(\d+)-(\d+)-(\d+)/;

$array[0] = $1;	# Dato
$array[1] = $2; # Maaned
$array[2] = $3; # Aarstal

er det samme som

my $txt ="4-11-2009";
my @array;
@array = $txt =~ /(\d+)-(\d+)-(\d+)/;

Links

One-liners

confusing eksempel 1

Onelineren nedenunder finder i alle filer som hedder .txt som extension steder hvor der står Fahrenheit temperaturer - fx. 56F - og udskifter dem med Celcius temperaturer - fx. 12C. Temperaturen omregnes med formlen Celsius = (Fahrenheit - 32) * 5/9

perl -pi -e 's{([-+]?\d+(\.d*)?)F\b}{sprintf "%.0fC",($1-32)*5/9}eg' *.txt

perl aktivering

Progammet startes med perl -pi -e 'ONELINER' hvor (Se hvid tekst i eksemplet herunder)

  • perloption p = Loop One-liner og indlæs filer linie for linie *.txt
    • Svarer til "while (<>) { ... }" omkring din One-liner.
  • perloption i = Editer filer direkte
  • perloption e = programlinie eller One-liner.
<input>perl -pi -e </input>'s{([-+]?\d+(\.d*)?)F\b}{sprintf "%.0fC",($1-32)*5/9}eg' <input>*.txt</input>

Search and replace

Eksemplet ovenfor anvender search and replace funktionen s/PATTERN/REPLACE/ som også kan skrives s{PATTERN}{REPLACE}. Se herunder.

perl -pi -e '<input>s{</input>([-+]?\d+(\.d*)?)F\b<input>}{</input>sprintf "%.0fC",($1-32)*5/9<input>}</input><notice>eg</notice>' *.txt

Search and replace funktionen anvender options e og g. Se med blåt ovenfor

  • Option e = Betragt REPLACE delen af searchfunktionen som et Perl expression - altså som program og ikke tekst. (sprintf funktionen)
  • Option g = global. Erstat alle der matcher. Ikke kun en gang.

Søge pattern

Mønstret der søges efter i filerne - linie for linie - er ([-+]?\d+(\d+(\.d*)?)F\b Se herunder.

perl -pi -e 's{<input>([-+]?\d+(\.d*)?)F\b</input>}{sprintf "%.0fC",($1-32)*5/9}eg' *.txt

Der ledes i linerne efter Fahrenheit grader skriver som for eksempel 12F, +12F, -12F, +12.123F og den numeriske del huskes. Altså ved +12.12F huskes +12.42.

Paranteserne i pattern

I Eksemplet herunder ses to måder at anvende paranteser på.

  • De hvide paranteser er anvendt som capture, altså det der matcher inde i de hvide paranteser skal huskes hvis der står et F for fahrenheit bagefter.
  • De blå paranteser anvendes som grouping. Det kan ses ved at der anvendes ? lige efter som betyder at det i de blå paranteser kan ske 0 eller 1 gang. (Enten er der decimaler i gradantallet eller også er der ikke.)
perl -pi -e 's{<input>(</input>[-+]?\d+<notice>(</notice>\.d*<notice>)</notice><error>?</error><input>)</input><error>F</error>\b}{sprintf "%.0fC",($1-32)*5/9}eg' *.txt

Selve søgemønsteret

perl -pi -e 's{<notice>(</notice><input>[-+]?\d+(\.d*)?<notice>)</notice>F\b</input>}{sprintf "%.0fC",($1-32)*5/9}eg' *.txt

Alt hvad der matcher mellem de blå paranteser huskes som $1.

  • [-+]? = tegnet - (minus) eller + kan stå 0 eller 1 gang.
  • \d+ = Der skal stå mindst et ciffer \d er ciffer + er en eller flere af forrige - altså cifferet.
  • (\.d*)? = Der kan være decimaler.
  • F\b = Der skal stå et stort F for fahrenheit og det skal være på en ordgrænse \b. Altså ikke flere tegn

Erstat pattern

Når søgningen matcher vil erstat delen udføres. Se hvid tekst nedenunder. Modifierne med blå tekst betyder eat erstat feltet er et perl expression som skal udføres og ikke bare tekst der skal erstattes med. g betyder globally at søg/erstat skal være global på linien.

perl -pi -e 's{([-+]?\d+(\.d*)?)F\b}{<input>sprintf "%.0fC",($1-32)*5/9</input>}<notice>eg</notice>' *.txt

perl expression i erstat pattern

Funktionen sprintf udføres med "%.0fC" hvilket betyder at der skal udskives et flydende decimaltal med 0 decimaler efterfulgt af et C for celsius. Efter kommaet står der ($1-32)*5/9 hvor $1 er temperaturen i Fahrenheit husket fra Pattern delen. det mellem de blå paranteser herunder. Formel Celsius = (Fahrenheit - 32) * 5/9 udføres og erstatter Fahrenheit tallet i filerne.

perl -pi -e 's{<notice>(<input>[-+]?\d+(\.d*)?</input>)</notice>F\b}{<input>sprintf "%.0fC",(<notice>$1</notice>-32)*5/9</input>}eg' *.txt