#!/usr/bin/env perl
use strict;
use 5.10.0;
 
#
# Regular expression examples for the technical seminar 
# 16/01/2014 
#

# let's set a string, e.g. a familiar URL
my $url = "http://www.astro.uni-bonn.de/~izzard/technical.html";
my $url0 = $url; # backup in case we destroy $url!

# are we using http, https, ftp, ..?
# (x|y|z) matches either x,y or z and puts the result in $1
$url =~ /(http|https|ftp)/;
say "1) You are using $1"; <>;

# but what about mms://, rtmp:// etc.? Perhaps this is better
$url =~ /(http|https|ftp|mms|rtmp)/;

# e.g.
"rtmp://http.com" =~ /(http|https|ftp|mms|rtmp)/;
say "2) You are using $1"; <>;

# although this is even better, note '\:' not ':'
$url =~ /(.*)\:/;  # dot '.' matches any character except newline '\n'
say "3) You are using $1"; <>;

# regexp match returns true on a match
if($url =~ /http\:/)
{
    say "3) You are using http";
}
else
{
    say "3) You are not using http\n";
}
<>;

# we can match more than one character at a time:
# * = zero or more
# + = one or more
if($url =~ /(t+)/)
{
    say "4a) t+ matches $1";
}
else
{
    say "4a) t+ fails to match";
}

if($url =~ /(tt+)/)
{
    say "4b) tt+ matches $1";
}
else
{
    say "4b) tt+ fails to match";
}

if($url =~ /(ttt+)/)
{
    say "4c) ttt+ matches $1";
}
else
{
    say "4c) ttt+ fails to match";
}
<>;

# or, use {m,n} to match m<= <=n of them
if($url=~/(w{1,5})/)
{
    say "5) Matched $1";
}
else
{
    say "5) Failed to match $1";
}
<>;

# Character matches:
# Use [...] to choose characters
# e.g. [abcd] matches either of a, b, c or d
# [a-z] matches one of a,b,c,d... x,y,z
# [a-zA-Z] matches any letter
# [0-9] matches any number
# [^0-9] matches any NOT-number (^ is the NOT symbol)

if($url=~/~([a-z]+)/)
{
    say "6) Matched $1";
}
<>;

# there are shorter forms:
# \d is the same as [0-9]
# \w is a word character [0-9A-Za-z_] (including underscore!)
# \s is a space
# \b is a word boundary
# 
# \D is the same as [^0-9]
# \W is the same as [^0-9A-Za-z_]
# \S is a non-space
#
# remember '.' matches anything except '\n' (in a normal regexp)

if($url=~/(\W\W\w+)/)
{
    say "7) Matched $1";
}
<>;

# Anchors:
# ^ matches the start of a string
# $ matches the end of a string
if($url=~/^(\w+)/)
{
    say "8) Matched $1";
}
<>;

if($url=~/(\w+)$/)
{
    say "9) Matched $1";
}
<>;

# multiple matches
$url=~/(.*)\/(.*)/;
say "10) homepage is $1; page is $2";
<>;

# repeated match : trailing 'g'
# Note that Perl returns matches in an array which you can capture
# (avoids $1, $2 etc.)
my @matches = ($url=~/(\w+)+/g);

foreach my $match (@matches)
{
    say "11) matched $match";
}
<>;

# ignore case a=A b=B etc.
if($url=~/(HTTP)/)
{
    say "12) matched $1";
}
else
{
    say "12) failed to match";
}
<>;

if($url=~/(HTTP)/i)
{
    say "13) matched $1";
}
else
{
    say "13) failed to match";
}
<>;

################
# SUBSTITUTION #
################
say "Substitution";

# use leading 's' to substitute
$url =~ s/http/ftp/;
say "1) \$url is now $url";
<>;

$url =~ s/izzard/norberto/;
say "2) \$url is now $url";
<>;

$url =~ s/(\w+)/>$1</;
say "3) \$url is now $url";
<>;

# global substitution
$url =~ s/(\w+)/>$1</g;
say "4) \$url is now $url";
<>;

$url=$url0;
say "Restored \$url to $url";

#
# Alternative delimiter
#
# You do not have to use /
# e.g. =~m!...! or =~s!...!...!
# 
# c.f. s/http\:\/\/www/zzz/
#   with
#      s!http\://www!zzz!
#
$url =~ s%(\w+)%>$1<%g;
say "5) \$url is now $url";
<>;

#
# Escaped characters
#
# \n newline
# \t tab
$url = "$url0\n";
say "The URL before the newline is ",
($url=~/(.*)/)[0];
<>;

# regular expression patterns in strings (dynamic patterns)
my $pattern = '(~\w+)';
if($url=~/$pattern/)
{
    say "Matched $1";
}
<>;

# Special variables:
#
# We already met $1, $2, $3... which are whatever is 
# matched in () ... () ... () ...
#
# There are more:
#
# $& contains whatever matches, $` before it, $' after it
#
$url=~/~\w+/;
say "Again, matched $&";
say "Before was $`";
say "After is $'";

# also note that 
#        /pattern/
# without a preceding string matches against $_ (the Perl default string)
