%% ================================================================================ %% This LaTeX file was created by AbiWord. %% AbiWord is a free, Open Source word processor. %% You may obtain more information about AbiWord at www.abisource.com %% ================================================================================ \documentclass[12pt]{article} \usepackage[T1]{fontenc} \usepackage{calc} \usepackage{hyperref}\usepackage{setspace} \usepackage{multicol} \usepackage[normalem]{ulem} \usepackage{color} \setlength{\oddsidemargin}{1.250000in-1in} \setlength{\textwidth}{\paperwidth - 1.250000in-1.250000in} \begin{document} \begin{center} \textbf{{\LARGE{}Perl and Regular Expressions}} \end{center} \begin{center} {\large{}Regular Expressions are available as part of the programming languages Java, JScript, Visual Basic and VBScript, JavaScript, C, C++, C\#, elisp, Perl, Python, Ruby, PHP, sed, awk, and in many applications, such as editors, grep, egrep.} \end{center} \begin{center} {\large{}Regular Expressions help you master your data.} \end{center} \begin{flushleft} \textbf{{\LARGE{}What is a Regular Expression?}} \end{flushleft} \begin{flushleft} {\Large{}Powerful.} \end{flushleft} \begin{flushleft} {\Large{}Low level description:} \end{flushleft} \begin{flushleft} {\large{}Describes some text} \end{flushleft} \begin{flushleft} {\large{}Can use to:} \end{flushleft} \begin{flushleft} Verify a user's input \end{flushleft} \begin{flushleft} Sift through large amounts of data \end{flushleft} \begin{flushleft} {\Large{}High level description:} \end{flushleft} \begin{flushleft} {\large{}Allow you to master your data} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Regular Expressions as a language}} \end{flushleft} \begin{flushleft} {\large{}Can consider regular expressions as a language} \end{flushleft} \begin{flushleft} {\large{}Made of two types of characters:} \end{flushleft} \begin{flushleft} \textit{Literal} characters \end{flushleft} \begin{flushleft} {\footnotesize{}Normal text characters} \end{flushleft} \begin{flushleft} {\footnotesize{}Like words of the program} \end{flushleft} \begin{flushleft} \textit{Metacharacters} \end{flushleft} \begin{flushleft} {\footnotesize{}The special characters }\textbf{{\footnotesize{}+ ? . * \^{} \$ ( ) [ \{ | \ensuremath{\backslash}}} \end{flushleft} \begin{flushleft} {\footnotesize{}Act as the grammar that combines with the words according to a set of rules to create and expression that communicates an idea} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{center} \textbf{{\LARGE{}How to use a Regular Expression}} \end{center} \begin{center} {\large{}How to make a regular expression as part of your program} \end{center} \begin{flushleft} \textbf{{\LARGE{}What do they look like?}} \end{flushleft} \begin{flushleft} {\Large{}In Perl, a regular expression begins and ends with }\textbf{{\Large{}/}}{\Large{}, like this: }\textbf{{\Large{}/abc/}} \end{flushleft} \begin{flushleft} \textbf{{\Large{}/abc/}}{\Large{} }{\Large{}matches the string "abc"} \end{flushleft} \begin{flushleft} {\large{}Are these literal characters or metacharacters?} \end{flushleft} \begin{flushleft} {\Large{}Returns true if matches, so often use as condition in an if statement} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Example: searching for "Course:"}} \end{flushleft} \begin{flushleft} {\large{}Problem: want to print all lines in all input files that contain the string "Course:"} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}while ( <> ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} my \$line = \$\_;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} if ( \$line =\~{} /Course:/ ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} print \$line;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} \}}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\}}} \end{flushleft} \begin{flushleft} {\large{}Or more concisely:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}while ( <> ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} print if \$\_ =\~{} /Course:/;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\}}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}The "match operator" }}\textbf{{\LARGE{}=\~{}}} \end{flushleft} \begin{flushleft} {\Large{}If just use /Course:/, this returns true if \$\_ contains the string Course:} \end{flushleft} \begin{flushleft} {\Large{}If want to test another string variable }\textbf{{\Large{}\$var}}{\Large{} to see if it contains the regular expression, use} \end{flushleft} \begin{flushleft} \textbf{{\Large{}\$var =\~{} /regular expression/}} \end{flushleft} \begin{flushleft} {\Large{}Under what condition is this true?} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}The "match operator" }}\textbf{{\LARGE{}=\~{} }}\textbf{{\LARGE{}2}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# sets the string to be searched:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = "perl for Win32";}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# is 'perl' inside \$\_? }} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( \$\_ =\~{} /perl/ ) \{ print "Found perl\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# Same as the regex above.}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# Don't need the =\~{} as we are testing \$\_:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /perl/ ) \{ print "Found perl\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}/i}}\textbf{{\LARGE{} Matching without case sensitivity}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = "perl for Win32";}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# this will fail because the case doesn't match:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /PeRl/ ) \{ print "Found PeRl\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# this will match, because there is an 'er' in 'perl':}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /er/ ) \{ print "Found er\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# this will match, because there is an 'n3' in 'Win32':}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /n3/ ) \{ print "Found n3\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# this will fail because the case doesn't match:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /win32/ ) \{ print "Found win32\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# This matches because the /i at the end means}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# "match without case sensitivity":}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /win32/i ) \{ print "Found win32 (i)\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Using }}\textbf{{\LARGE{}!\~{}}}\textbf{{\LARGE{} instead of }}\textbf{{\LARGE{}=\~{}}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# Looking for a space:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "Found!\ensuremath{\backslash}n" if / /;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# both these are the same, but reversing the logic with}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# unless and !\~{}}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "Found!!\ensuremath{\backslash}n" unless \$\_ !\~{} / /;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "Found!!\ensuremath{\backslash}n" unless ! / /;}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Embedding variables in regexps}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# Create two variables containing regular expressions}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# to search for:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}my \$find = 32;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}my \$find2 = " for ";}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /\$find/ ) \{ print "Found '\$find'\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}if ( /\$find2/ ) \{ print "Found '\$find2'\ensuremath{\backslash}n" \};}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# different way to do the above:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "Found \$find2\ensuremath{\backslash}n" if /\$find2/; }} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{center} \textbf{{\LARGE{}The Metacharacters}} \end{center} \begin{center} {\large{}The funny characters} \end{center} \begin{center} {\large{}What they do} \end{center} \begin{center} {\large{}How to use them} \end{center} \begin{flushleft} \textbf{{\LARGE{}Character Classes }}\textbf{{\LARGE{}[...]}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}my @names = ( "Nick", "Albert", "Alex", "Pick" );}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}foreach my \$name ( @names ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} if ( \$name =\~{} /[NP]ick/ ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} print "\$name: Out for a Pick Nick\ensuremath{\backslash}n";}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} else \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} print "\$name is not Pick or Nick\ensuremath{\backslash}n";}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} \}}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\}}} \end{flushleft} \begin{flushleft} Square brackets \textit{match a single character} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Examples of use of }}\textbf{{\LARGE{}[...]}} \end{flushleft} \begin{flushleft} {\Large{}Match a capital letter: }\textbf{{\Large{}[ABCDEFGHIJKLMNOPQRSTUVWXYZ]}} \end{flushleft} \begin{flushleft} {\Large{}Same thing:}\textbf{{\Large{} [A-Z]}} \end{flushleft} \begin{flushleft} {\Large{}Match a vowel: }\textbf{{\Large{}[aeiou]}} \end{flushleft} \begin{flushleft} {\Large{}Match a letter or digit: }\textbf{{\Large{}[A-Za-z0-9]}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Negated character class: }}\textbf{{\LARGE{}[\^{}...]}} \end{flushleft} \begin{flushleft} {\Large{}Match any single character that is }\textit{{\Large{}not}}{\Large{} a letter: }\textbf{{\Large{}[\^{}A-Za-z]}} \end{flushleft} \begin{flushleft} {\Large{}Match any character that is not a space or a tab: }\textbf{{\Large{}[\^{} \ensuremath{\backslash}t]}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Example using }}\textbf{{\LARGE{}[\^{}...]}} \end{flushleft} \begin{flushleft} This simple program prints only lines that contain characters that are not a space: \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}while ( <> )}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}\{}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{} print \$\_ if /[\^{} ]/;}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}\}}} \end{flushleft} \begin{flushleft} This prints lines that \textit{start with} a character that is not a space: \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}while ( <> )}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}\{}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{} print \$\_ if /\^{}[\^{} ]/;}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}\}}} \end{flushleft} \begin{flushleft} Notice that \textbf{\^{}} has two meanings: one inside \textbf{[...]}, the other outside. \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Shorthand for Common Character Classes}} \end{flushleft} \begin{flushleft} {\large{}Since matching a digit is very common, Perl provides }\textbf{{\large{}\ensuremath{\backslash}d}}{\large{} as a short way of writing \\}\textbf{{\large{}[0-9]}} \end{flushleft} \begin{flushleft} \textbf{{\large{}\ensuremath{\backslash}D}}{\large{} matches a non-digit: }\textbf{{\large{}[\^{}0-9]}} \end{flushleft} \begin{flushleft} \textbf{{\large{}\ensuremath{\backslash}s}}{\large{} matches any whitespace character; shorthand for }\textbf{{\large{}[ \ensuremath{\backslash}t\ensuremath{\backslash}n\ensuremath{\backslash}r\ensuremath{\backslash}f]}} \end{flushleft} \begin{flushleft} \textbf{{\large{}\ensuremath{\backslash}S}}{\large{} non-whitespace, }\textbf{{\large{}[\^{} \ensuremath{\backslash}t\ensuremath{\backslash}n\ensuremath{\backslash}r\ensuremath{\backslash}f]}} \end{flushleft} \begin{flushleft} \textbf{{\large{}\ensuremath{\backslash}w}}{\large{} word character, }\textbf{{\large{}[a-zA-Z0-9\_]}} \end{flushleft} \begin{flushleft} \textbf{{\large{}\ensuremath{\backslash}W}}{\large{} non-word character, }\textbf{{\large{}[\^{} a-zA-Z0-9\_]}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Matching any character}} \end{flushleft} \begin{flushleft} {\Large{}The dot matches any character except a newline} \end{flushleft} \begin{flushleft} {\Large{}This matches any line with at least 5 characters:} \end{flushleft} \begin{flushleft} \textbf{{\Large{}print if /...../;}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Matching the beginning or end}} \end{flushleft} \begin{flushleft} {\Large{}to match a line that contains exactly five characters:} \end{flushleft} \begin{flushleft} \textbf{{\Large{}print if /\^{}.....\$/;}} \end{flushleft} \begin{flushleft} {\Large{}the \^{} matches the beginning of the line.} \end{flushleft} \begin{flushleft} {\Large{}the \$ matches at the end of the line} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Matching Repetitions: }}\textbf{{\LARGE{}* + ? \{n,m\}}} \end{flushleft} \begin{flushleft} {\large{}To match zero or more:} \end{flushleft} \begin{flushleft} {\large{}/a*/ will match zero or more letter a, so matches "", "a", "aaaa", "qwereqwqwer", or the nothing in front of }\textit{{\large{}anything}}{\large{}!} \end{flushleft} \begin{flushleft} {\large{}to match at least one:} \end{flushleft} \begin{flushleft} {\large{}/a+/ matches at least one "a"} \end{flushleft} \begin{flushleft} {\large{}/a?/ matches zero or one "a"} \end{flushleft} \begin{flushleft} {\large{}/a\{3,5\}/ matches between 3 and 5 "a"s.} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Example using .*}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = 'Nick Urbanik ';}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "found something in <>\ensuremath{\backslash}n" if /<.*>/;}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# Find everything between quotes:}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = 'He said, "Hi there!", and then "What\ensuremath{\backslash}'s up?"';}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "quoted!\ensuremath{\backslash}n" if /"[\^{}"]*"/;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "too much!\ensuremath{\backslash}n" if /".*"/;}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Capturing the Match with }}\textbf{{\LARGE{}(...)}} \end{flushleft} \begin{flushleft} {\Large{}Often want to scan large amounts of data, extracting important items} \end{flushleft} \begin{flushleft} {\Large{}Use parentheses and regular expressions} \end{flushleft} \begin{flushleft} {\Large{}Silly example of capturing an email address:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = 'Nick Urbanik ';}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "found \$1 in <>\ensuremath{\backslash}n" if /<(.*)>/;}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Capturing the match: greediness}} \end{flushleft} \begin{flushleft} {\large{}Look at this example:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = 'He said, "Hi there!", and then "What\ensuremath{\backslash}'s up?"';}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "\$1\ensuremath{\backslash}n" if /"([\^{}"]*)"/;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "\$1\ensuremath{\backslash}n" if /"(.*)"/;}} \end{flushleft} \begin{flushleft} {\large{}What will each print?} \end{flushleft} \begin{flushleft} {\large{}The first one works; the second one prints:\\}\textbf{{\footnotesize{}Hi there!", and then "What's up?}} \end{flushleft} \begin{flushleft} {\large{}Why?} \end{flushleft} \begin{flushleft} {\large{}Because *, ?, +, \{m,n\} are }\textit{{\large{}greedy}}{\large{}!} \end{flushleft} \begin{flushleft} {\large{}They match as much as they possibly can!} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Being Stingy (not Greedy): }}\textbf{{\LARGE{}?}} \end{flushleft} \begin{flushleft} {\Large{}Usually greedy matching is what we want, but not always} \end{flushleft} \begin{flushleft} {\Large{}How can we match as little as possible?} \end{flushleft} \begin{flushleft} {\Large{}Put a ? after the quantifier:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}*? }}{\footnotesize{}Match 0 or more times} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}+? }}{\footnotesize{}Match 1 or more times} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}?? }}{\footnotesize{}Match 0 or 1 time} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\{n,\}? }}{\footnotesize{}Match at least n times} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\{n,m\}? }}{\footnotesize{}Match at least n, but no more than m times} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Being Less Greedy: Example}} \end{flushleft} \begin{flushleft} {\Large{}We can solve the problem we saw earlier using non-greedy matching:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\$\_ = 'He said, "Hi there!", and then "What\ensuremath{\backslash}'s up?"';}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "\$1\ensuremath{\backslash}n" if /"([\^{}"]*)"/;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}print "\$1\ensuremath{\backslash}n" if /"(.*?)"/;}} \end{flushleft} \begin{flushleft} {\Large{}These both work, and match only\\}\textbf{{\footnotesize{}Hi there!}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Sifting through large amounts of data}} \end{flushleft} \begin{flushleft} {\Large{}Imagine you need to create computing accounts for thousands of students} \end{flushleft} \begin{flushleft} {\Large{}As input, you have data of the form:} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}Some heading on the top of each page}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}More headings with other content, including blank lines}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}A tab character separates the columns}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}123456789 H123456(1)}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}234567890 I234567(2)}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}345678901 J345678(3)}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}... ...}} \end{flushleft} \begin{flushleft} \textbf{{\scriptsize{}987654321 A123456(1)}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Capturing the Match: }}\textbf{{\LARGE{}(...)}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# useradd() is a function defined elsewhere}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# that creates a computer account with}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# username as first parameter, password as}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\# the second parameter}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}while ( <> ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} if ( /\^{}(\ensuremath{\backslash}d\{9\})\ensuremath{\backslash}t([A-Z]\ensuremath{\backslash}d\{6\}\ensuremath{\backslash}([\ensuremath{\backslash}dA]\ensuremath{\backslash}))/ ) \{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} my \$student\_id = \$1;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} my \$hk\_id = \$2;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} useradd( \$student\_id, \$hk\_id );}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\}}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}The Substitution Operator }}\textbf{{\LARGE{}s///}} \end{flushleft} \begin{flushleft} {\large{}Sometimes want to replace one string with another (editing)} \end{flushleft} \begin{flushleft} {\large{}Example: want to replace Nicholas with Nick on input files:} \end{flushleft} \begin{flushleft} \textbf{while ( <> )} \end{flushleft} \begin{flushleft} \textbf{\{} \end{flushleft} \begin{flushleft} \textbf{ \$\_ =\~{} s/Nicholas/Nick/;} \end{flushleft} \begin{flushleft} \textbf{ print \$\_;} \end{flushleft} \begin{flushleft} \textbf{\}} \end{flushleft} \begin{flushleft} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Avoiding leaning toothpicks: }}\textbf{{\LARGE{}/\ensuremath{\backslash}/\ensuremath{\backslash}/}} \end{flushleft} \begin{flushleft} {\footnotesize{}Want to change a filename, edit the directory in the path from, say /usr/local/bin/filename to /usr/bin/filename} \end{flushleft} \begin{flushleft} {\footnotesize{}Could do like this:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}s/\ensuremath{\backslash}/usr\ensuremath{\backslash}/local\ensuremath{\backslash}/bin\ensuremath{\backslash}//\ensuremath{\backslash}/usr/\ensuremath{\backslash}bin\ensuremath{\backslash}//;}} \end{flushleft} \begin{flushleft} {\footnotesize{}but this makes me dizzy!} \end{flushleft} \begin{flushleft} {\footnotesize{}We can do this instead:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}s!\ensuremath{\backslash}/usr/local/bin/!/usr/bin/!;}} \end{flushleft} \begin{flushleft} {\footnotesize{}Can use any character instead of }\textbf{{\footnotesize{}/}}{\footnotesize{} in }\textbf{{\footnotesize{}s///}} \end{flushleft} \begin{flushleft} {\footnotesize{}For }\textit{{\footnotesize{}matches}}{\footnotesize{}, can put }\textbf{{\footnotesize{}m//}}{\footnotesize{}, and use any char instead of /} \end{flushleft} \begin{flushleft} {\footnotesize{}Can also use parentheses or braces:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}s\{...\}\{...\}}}{\footnotesize{} or }\textbf{{\footnotesize{}m\{...\}}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Substitution and the }}\textbf{{\LARGE{}/g}}\textbf{{\LARGE{} modifier}} \end{flushleft} \begin{flushleft} {\large{}If an input line contains:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}Nicholas Urbanik read "Nicholas Nickleby"}} \end{flushleft} \begin{flushleft} {\large{}then the output is:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}Nick Urbanik read "Nicholas Nickleby"}} \end{flushleft} \begin{flushleft} {\large{}How change all the Nicholas in one line?} \end{flushleft} \begin{flushleft} {\large{}Use the }\textbf{{\large{}/g}}{\large{} (global) modifier:} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}while ( <> )}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\{}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} \$\_ =\~{} s/Nicholas/Nick/g;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{} print \$\_;}} \end{flushleft} \begin{flushleft} \textbf{{\footnotesize{}\}}} \end{flushleft} \begin{flushleft} \textbf{{\LARGE{}Making regular expressions readable: /x modifier}} \end{flushleft} \begin{flushleft} {\Large{}Sometimes regular expressions can get long, and need comments inside so others (or you later!) understand} \end{flushleft} \begin{flushleft} {\Large{}Use /x at the end of s///x or m//x} \end{flushleft} \begin{flushleft} {\Large{}Allows white space, newlines, comments} \end{flushleft} \begin{flushleft} \end{flushleft} \end{document}