| I l@ve RuBoard |
SMTP is an acronym for Simple Mail Transfer Protocol. This is an Internet standard, specified in RFC-821, and as its name implies, is a protocol for transferring mail messages. When an SMTP server receives a piece of mail, it does one of two things: forwards the email to a host closer to the intended recipient, or if the recipient is local, places the email in the recipient's mailbox. Thus, SMTP provides a technique for putting messages in a mailbox, but it doesn't define a technique for retrieving existing messages from a mailbox. To this end, the Post Office Protocol, Version 3 (POP3) has been designed, as specified in RFC-1725. Its explicit purpose is to allow remote access to a mailbox managed on a remote computer.
In practice, this means that SMTP can send Internet email, and POP3 can retrieve Internet email.
As is common for Internet protocols, both mail protocols use a simple conversation between a client and a server. This conversation is "line-based" (meaning all commands and responses are sent as complete lines) and works exclusively with 7-bit ASCII data. Each protocol defines its own special command and response sequence to support its various options.
The mail messages handled by both these protocols must be formatted as specified in various RFCs, starting with RFC-822, to the latest, which is RFC-1521. In a nutshell, these RFCs define the format of the message header (a list of headers for the message, including the subject, recipient information, etc.), and the message body . The message body must consist of 7-bit ASCII and may optionally include a number of different sections. These sections typically encode binary attachments or alternative renderings of the message text. Messages with multiple sections are typically referred to as Multipurpose Internet Mail Extensions (MIME) messages. Unfortunately, MIME is a complex beast and beyond the scope of this chapter. Python does support various MIME standards, but using and packing everything into an email message is not for the faint hearted. If you have this requirement, and Microsoft Exchange or a slightly higher-level email system is available, you should consider using that.
To begin, we'll use Python to send a simple message using the SMTP protocol. Our message will contain the minimum number of message headers, a plain ASCII message body, and no attachments.
To assist in this task, we'll use the Python module smtplib . This module contains a single class, SMTP , that manages the connection with the SMTP server and provides useful methods for interacting with the server.
Sending a simple message using SMTP is so simple it's not worth writing a sample source file for this purpose; you can do it at the interactive window. The SMTP class provides the following method:
bad_addresses = sendmail( from, to, message )
A string with the address of the sender.
A list of strings, one for each recipient.
A message as a string formatted as specified in the various RFCs.
So all you need is the message itself, a list of recipients, and your own email address.
As per RFC-822, the format of the message is simple. It consists of a list of message headers, followed by a blank line, followed by the message body. For this demonstration, you can set up a message with the following code:
>>> msg="Subject: Hi from Python\n\nHello."
Define the subject of the message as "Hi from Python" and the body as "Hello."
Next, define a variable with your email address and SMTP host:
>>><EMAIL_ADDRESS>>>> host="mail-hub"
And send the message to yourself:
>>> import smtplib >>> s=smtplib.SMTP(host) >>> s.sendmail(address, [address], msg) {}
The result from this function is a dictionary of email addresses in the to list that failed; the dictionary is keyed by the email address, with the error message as the value. In this example you received an empty dictionary, so everything went OK. See the smtplib module documentation for more information on error handling.
POP3 downloads messages from a remote mailbox. As we discussed previously, SMTP is used typically to send Internet email messages, and POP3 receives them.
Like most Internet protocols, POP3 uses a line-based communications protocol, and also like most Internet protocols, you will find a Python module designed to ease working with that protocol; in this case the Python module is poplib .
Before delving into a discussion of POP3, it is worth noting that an improved protocol known as Internet Message Access Protocol (IMAP) has been designed. Although this fixes many of the shortcomings in the POP3 protocol, it's not used as widely as POP3. Therefore, we will discuss using POP3 to ensure the code works on the widest possible range of mail servers. If you need to investigate using the IMAP protocol, you should view the module imaplib and its associated documentation.
There are three steps to establishing a connection to a POP3 mailbox:
Connect to the server by creating a poplib.POP3() instance, specifying the hostname.
Send the mailbox password using the pass_() method (pass is a reserved word in Python, hence the trailing underscore).
You now have a valid connection, and the mailbox is locked. While the mailbox is locked, no other connections are possible, so it's important to unlock the mailbox when you're done using the quit() method. If you don't unlock the mailbox, other mail clients (such as your regular email client) won't be able to connect until the connection times out, which may take some time. It would be appropriate to use a Python finally block for this purpose, as the example will show.
POP3 messages are numbered from 1-n, where n is the number of messages currently in the mailbox. Obviously, these message numbers are not unique and are valid only for the given session. So the first step to reading the mailbox is to determine the number of messages in the mailbox using the stat() method. Then you can request each message by number. For the first example, don't bother looping over all the messages, but, instead, just look at the first message:
# DumpPop.py - Dumps the first message in a POP3 mailbox. import sys import poplib def DumpAPopMessage(host, user, password): # Establish a connection to the POP server. a = poplib.POP3(host) # Note we print the server response, although not necessary! print a.user(user) print a.pass_(password) # The mailbox is now locked - ensure we unlock it! try: (numMsgs, totalSize) = a.stat() if numMsgs == 0: print "Sorry - there are no messages in the mailbox" else: (server_msg, body, octets) = a.retr(1) print "Server Message:", server_msg print "Number of Octets:", octets print "Message body:" for line in body: print line finally: print a.quit() if __name__=='__main__': if len(sys.argv)<4: print "Usage:", sys.argv[0], "host username password" else: DumpAPopMessage(sys.argv[1], sys.argv[2], sys.argv[3])
As you can see, the example expects you to pass the hostname, the username, and password on the command line. You can test the script from the command prompt, as the following output shows:
C:\Scripts>DumpPop.py pop-server mhammond topsecret +OK Password required for mhammond +OK mhammond's maildrop has 1 messages (1730 octets) Server Message: +OK 1730 octets Number of Octets: 1730 Message body: Return-Path<EMAIL_ADDRESS>Received: from mr4.vic-remote.bigpond.net.au ([<IP_ADDRESS>]) by m5.bigpond.net.au (Netscape Messaging Server 3.54) with ESMTP id AAA26FD for<EMAIL_ADDRESS>Thu, 15 Jul 1999 21:01:30 +1000 ... Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3 Hello +OK m5.bigpond.net.au POP3 server closing connection C:\Scripts>
This is the same message you sent previously. Notice all the headers this message now has; even though you specified only a few, the mail transport system has added many more. The output shown has had many headers removed for brevity.
At this point you may start to get a little worried. Looking at the code, you can see the message is returned as a list of lines, but many of those lines are headers. Worse, some of the headers are split over multiple lines (as supported by the relevant RFC). Does this mean you need to understand all this before doing anything useful?
Fortunately, Python has library support for parsing and using data of this format. The most basic support can be found in the rfc822.Message class, but the mimetools module supports an extension to this class that supports the various MIME extensions (as described earlier). Since MIME is an extension to the basic standard, you can safely use it even for non-MIME messages.
A slight complication is that the mimetools.Message() class expects to receive a file object from which it obtains its data, rather than a list of lines! The StringIO (or cStringIO) module can make a file object from a string, but there is a list of strings. The simplest solution is to join the list back into a huge string and feed that into cStringIO.
Once you create mimetools.Message(), all the headers are read, and the file is positioned at the start of the body. You can then use the various methods to examine the headers. Depending on the message content, you can either read the rest of the file to obtain the body or use some of the MIME-specific features to process the various sections.
You can now modify the example to take advantage of this class. Loop over all messages in the mailbox and examine the Subject header for the test message. When you find the message, print the message body and delete the message.
The significant additions to the new example are:
A loop to examine all the messages.
Using cStringIO to create a file object as discussed.
Examine the Subject header of each message using the getheader() method.
Delete the message with the dele() method of the POP3 session.
# DumpPop2.py - Dumps and deletes a test message from a POP3 mailbox. import sys import poplib import string import mimetools import cStringIO def DumpAPopMessage(host, user, password): # Establish a connection to the POP server. a = poplib.POP3(host) # Note we print the server response, although not necessary! print a.user(user) print a.pass_(password) # The mailbox is now locked - ensure we unlock it! try: (numMsgs, totalSize) = a.stat() for thisNum in range(1, numMsgs+1): (server_msg, body, octets) = a.retr(1) # Create a file like object suitable for the # mimetools.Message class. pseudo_file = cStringIO.StringIO(string.join(body, '\n')) msg = mimetools.Message(pseudo_file) if msg.getheader("Subject")=="Hi from Python": print "Found our test message" print "Body is", `pseudo_file.read()` print a.dele(thisNum) print "Message deleted!" finally: print a.quit() if __name__=='__main__': if len(sys.argv)<4: print "Usage:", sys.argv[0], "host username password" else: DumpAPopMessage(sys.argv[1], sys.argv[2], sys.argv[3])
You can run this example using parameters identical to the previous example:
C:\Scripts>DumpPop2.py pop-server mhammond topsecret +OK Password required for mhammond +OK mhammond's maildrop has 1 messages (1243 octets) Found our test message Body is 'Hello' +OK Message 1 deleted Message deleted! +OK m5.bigpond.net.au POP3 server closing connection C:\Scripts>
If you experiment with this code, you'll see that the Message class has correctly handled the continuation of long header lines. Working with the message headers is made far simpler with the mimetools.Message class and worth the small hoops you need to jump through to use it.
| I l@ve RuBoard |


- onAuthComplete(AudioJackReader, int) - Method in interface com.acs.audiojack.AudioJackReader.OnAuthCompleteListener
-
Called when the reader authentication is complete.
- onCustomIdAvailable(AudioJackReader, byte[]) - Method in interface com.acs.audiojack.AudioJackReader.OnCustomIdAvailableListener
-
Called when the reader sent the custom ID.
- onDeviceIdAvailable(AudioJackReader, byte[]) - Method in interface com.acs.audiojack.AudioJackReader.OnDeviceIdAvailableListener
-
Called when the reader sent the device ID.
- onDukptOptionAvailable(AudioJackReader, boolean) - Method in interface com.acs.audiojack.AudioJackReader.OnDukptOptionAvailableListener
-
Called when the reader sent the DUKPT option.
- onFirmwareVersionAvailable(AudioJackReader, String) - Method in interface com.acs.audiojack.AudioJackReader.OnFirmwareVersionAvailableListener
-
Called when the reader sent the firmware version.
- onPiccAtrAvailable(AudioJackReader, byte[]) - Method in interface com.acs.audiojack.AudioJackReader.OnPiccAtrAvailableListener
-
Called when the reader sent the ATR from PICC.
- onPiccResponseApduAvailable(AudioJackReader, byte[]) - Method in interface com.acs.audiojack.AudioJackReader.OnPiccResponseApduAvailableListener
-
Called when the reader sent the response APDU from PICC.
- onRawDataAvailable(AudioJackReader, byte[]) - Method in interface com.acs.audiojack.AudioJackReader.OnRawDataAvailableListener
-
Called when the reader sent the raw data.
- onResetComplete(AudioJackReader) - Method in interface com.acs.audiojack.AudioJackReader.OnResetCompleteListener
-
Called when the reader reset is complete.
- onResultAvailable(AudioJackReader, Result) - Method in interface com.acs.audiojack.AudioJackReader.OnResultAvailableListener
-
Called when the reader sent the result.
- onStatusAvailable(AudioJackReader, Status) - Method in interface com.acs.audiojack.AudioJackReader.OnStatusAvailableListener
-
Called when the reader sent the status.
- onTrackDataAvailable(AudioJackReader, TrackData) - Method in interface com.acs.audiojack.AudioJackReader.OnTrackDataAvailableListener
-
Called when the reader sent the track data.
- onTrackDataNotification(AudioJackReader) - Method in interface com.acs.audiojack.AudioJackReader.OnTrackDataNotificationListener
-
Called when the reader notified the track data.
- onTrackDataOptionAvailable(AudioJackReader, int) - Method in interface com.acs.audiojack.AudioJackReader.OnTrackDataOptionAvailableListener
-
Called when the reader sent the track data option.


| Class | ManageSieve |
| In: |
managesieve.rb
|
| Parent: | Object |
ManageSieve implements MANAGESIEVE, a protocol for remote management of Sieve scripts.
The following MANAGESIEVE commands are implemented:
The AUTHENTICATE command is partially implemented. Currently the LOGIN and PLAIN authentication mechanisms are implemented.
# Create a new ManageSieve instance m = ManageSieve.new( :host => 'sievehost.mydomain.com', :port => 2000, :user => 'johndoe', :password => 'secret', :auth => 'PLAIN' ) # List installed scripts m.scripts.sort do |name, active| print name print active ? " (active)\n" : "\n" end script = <<__EOF__ require "fileinto"; if header :contains ["to", "cc"]<EMAIL_ADDRESS>{ fileinto "Ruby-talk"; } __EOF__ # Test if there's enough space for script 'foobar' puts m.have_space?('foobar', script.length) # Upload it m.put_script('foobar', script) # Show its contents puts m.get_script('foobar') # Close the connection m.logout
| SIEVE_PORT | = | 2000 |
| capabilities | [R] | |
| euser | [R] | |
| host | [R] | |
| login_mechs | [R] | |
| port | [R] | |
| tls | [R] | |
| user | [R] |
Create a new ManageSieve instance. The info parameter is a hash with the following keys:
# File managesieve.rb, line 125 125: def initialize(info) 126: @host = info[:host] 127: @port = info[:port] || 2000 128: @user = info[:user] 129: @euser = info[:euser] || @user 130: @password = info[:password] 131: @auth_mech = info[:auth] || 'ANONYMOUS' 132: @tls = info.has_key?(:tls) ? !!info[:tls] : nil 133: 134: @capabilities = [] 135: @login_mechs = [] 136: @implementation = '' 137: @supports_tls = false 138: @socket = TCPSocket.new(@host, @port) 139: 140: data = get_response 141: server_features(data) 142: 143: if @tls and not supports_tls? 144: raise SieveNetworkError, 'Server does not support TLS' 145: @socket.close 146: elsif @tls != false 147: @tls = supports_tls? 148: starttls if @tls 149: end 150: 151: authenticate 152: @password = nil 153: end
Deletes script from the server.
# File managesieve.rb, line 189 189: def delete_script(script) 190: send_command('DELETESCRIPT', sieve_name(script)) 191: end
Returns the contents of script as a string.
# File managesieve.rb, line 172 172: def get_script(script) 173: begin 174: data = send_command('GETSCRIPT', sieve_name(script)) 175: rescue SieveCommandError => e 176: raise e, "Cannot get script: #{e}" 177: end 178: return data.to_s.chomp 179: end
Returns true if there is space on the server to store script with size size and false otherwise.
# File managesieve.rb, line 200 200: def have_space?(script, size) 201: begin 202: args = sieve_name(script) + ' ' + size.to_s 203: send_command('HAVESPACE', args) 204: return true 205: rescue SieveCommandError 206: return false 207: end 208: end
Disconnect from the server.
# File managesieve.rb, line 216 216: def logout 217: send_command('LOGOUT') 218: @socket.close 219: end
Uploads script to the server, using data as its contents.
# File managesieve.rb, line 182 182: def put_script(script, data) 183: args = sieve_name(script) 184: args += ' ' + sieve_string(data) if data 185: send_command('PUTSCRIPT', args) 186: end
If a block is given, calls it for each script stored on the server, passing its name and status as parameters. Else, and array of [ name, status ] arrays is returned. The status is either ‘ACTIVE’ or nil.
# File managesieve.rb, line 160 160: def scripts 161: begin 162: scripts = send_command('LISTSCRIPTS') 163: rescue SieveCommandError => e 164: raise e, "Cannot list scripts: #{e}" 165: end 166: return scripts unless block_given? 167: scripts.each { |name, status| yield(name, status) } 168: end
Sets script as active.
# File managesieve.rb, line 194 194: def set_active(script) 195: send_command('SETACTIVE', sieve_name(script)) 196: end


Write a generic data type for a deque and a randomized queue. The goal of this assignment is to implement elementary data structures using arrays and linked lists, and to introduce you to generics and iterators.
Dequeue. A double-ended queue or deque (pronounced "deck") is a generalization of a stack and a queue that supports adding and removing items from either the front or the back of the data structure. Create a generic data type Deque that implements the following API:
public class Deque<Item> implements Iterable<Item> { public Deque() // construct an empty deque public boolean isEmpty() // is the deque empty? public int size() // return the number of items on the deque public void addFirst(Item item) // add the item to the front public void addLast(Item item) // add the item to the end public Item removeFirst() // remove and return the item from the front public Item removeLast() // remove and return the item from the end public Iterator<Item> iterator() // return an iterator over items in order from front to end public static void main(String[] args) // unit testing (optional) }
Corner cases. Throw a java.lang.NullPointerException if the client attempts to add a null item; throw a java.util.NoSuchElementException if the client attempts to remove an item from an empty deque; throw a java.lang.UnsupportedOperationException if the client calls the remove() method in the iterator; throw a java.util.NoSuchElementException if the client calls the next() method in the iterator and there are no more items to return.
Performance requirements. Your deque implementation must support each deque operation in constant worst-case time. A deque containing n items must use at most 48n + 192 bytes of memory. and use space proportional to the number of items currently in the deque. Additionally, your iterator implementation must support each operation (including construction) in constant worst-case time.
Randomized queue. A randomized queue is similar to a stack or queue, except that the item removed is chosen uniformly at random from items in the data structure. Create a generic data type RandomizedQueue that implements the following API:
public class RandomizedQueue<Item> implements Iterable<Item> { public RandomizedQueue() // construct an empty randomized queue public boolean isEmpty() // is the queue empty? public int size() // return the number of items on the queue public void enqueue(Item item) // add the item public Item dequeue() // remove and return a random item public Item sample() // return (but do not remove) a random item public Iterator<Item> iterator() // return an independent iterator over items in random order public static void main(String[] args) // unit testing (optional) }
Corner cases. The order of two or more iterators to the same randomized queue must be mutually independent; each iterator must maintain its own random order. Throw a java.lang.NullPointerException if the client attempts to add a null item; throw a java.util.NoSuchElementException if the client attempts to sample or dequeue an item from an empty randomized queue; throw a java.lang.UnsupportedOperationException if the client calls the remove() method in the iterator; throw a java.util.NoSuchElementException if the client calls the next() method in the iterator and there are no more items to return.
Performance requirements. Your randomized queue implementation must support each randomized queue operation (besides creating an iterator) in constant amortized time. That is, any sequence of m randomized queue operations (starting from an empty queue) should take at most cm steps in the worst case, for some constant c. A randomized queue containing n items must use at most 48n + 192 bytes of memory. Additionally, your iterator implementation must support operations next() and hasNext() in constant worst-case time; and construction in linear time; you may (and will need to) use a linear amount of extra memory per iterator.
Permutation client. Write a client program Permutation.java that takes a command-line integer k; reads in a sequence of strings from standard input using StdIn.readString(); and prints exactly k of them, uniformly at random. Print each item from the sequence at most once. You may assume that 0 ≤ k ≤ n, where n is the number of string on standard input.
The running time of Permutation must be linear in the size of the input. You may use only a constant amount of memory plus either one Deque or RandomizedQueue object of maximum size at most n. (For an extra challenge, use only one Deque or RandomizedQueue object of maximum size at most k.) It must have the following API:% more distinct.txt % more duplicates.txt A B C D E F G H I AA BB BB BB BB BB CC CC % java Permutation 3 < distinct.txt % java Permutation 8 < duplicates.txt C BB G AA A BB CC % java Permutation 3 < distinct.txt BB E BB F CC G BB
public class Permutation { public static void main(String[] args) }
Deliverables. Submit only Deque.java, RandomizedQueue.java, and Permutation.java. We will supply algs4.jar. Do not call library functions except those in StdIn, StdOut, StdRandom, java.lang, java.util.Iterator, and java.util.NoSuchElementException. In particular, do not use either java.util.LinkedList or java.util.ArrayList.


We have seen two basic elements in an expression:
A value expressed as a literal or a variable.
An operator.
 Any character, except the metacharacters in Table 3.1, is interpreted as a literal that matches only itself.
| Special | |
|---|---|
| Characters | Usage |
| . | Matches any single character except newline. In awk, dot can match newline also. |
| * | Matches any number (including zero) of the single character (including a character specified by a regular expression) that immediately precedes it. |
| [...] | Matches any one of the class of characters enclosed between the brackets. A circumflex (^) as first character inside brackets reverses the match to all characters except newline and those listed in the class. In awk, newline will also match. A hyphen (-) is used to indicate a range of characters. The close bracket (]) as the first character in class is a member of the class. All other metacharacters lose their meaning when specified as members of a class. |
| ^ | First character of regular expression, matches the beginning of the line. Matches the beginning of a string in awk, even if the string contains embedded newlines. |
| $ | As last character of regular expression, matches the end of the line. Matches the end of a string in awk, even if the string contains embedded newlines. |
| \{n,m\} | Matches a range of occurrences of the single character (including a character specified by a regular expression) that immediately precedes it. \{n\} will match exactly n occurrences, \{n,\} will match at least n occurrences, and \{n,m\} will match any number of occurrences between n and m. (sed and grep only, may not be in some very old versions.) |
| \ |
[2] Most awk implementations do not yet support this notation.
Metacharacters have a special meaning in regular expressions,
much the same way as +
and *
have special meaning in
arithmetic expressions.
Several of the metacharacters (+ ? () |)
are available only as part of the extended
set used by programs such as egrep and awk.
We will look at what each metacharacter does
in upcoming sections, beginning with the backslash.
The backslash (\) metacharacter transforms metacharacters into ordinary characters (and ordinary characters into metacharacters). It forces the literal interpretation of any metacharacter such that it will match itself. For instance, the dot (.) is a metacharacter that needs to be escaped with a backslash if you want to match a period. This regular expression matches a period followed by three spaces.
\.
The backslash is typically used to match troff requests or macros that begin with a dot.
\.nf
You can also use the backslash to escape the backslash. For instance, the font change request in troff is "\f". To search for lines containing this request, you'd use the following regular expression:
\\f
In addition, sed uses the backslash to cause a group of ordinary characters to be interpreted as metacharacters, as shown in Figure 3.2.
The n in the "\n" construct represents a digit from 1 to 9; its use will be explained in Chapter 5, Basic sed Commands.
The wildcard metacharacter, or dot (.), might be considered equivalent to a variable. A variable represents any value in an arithmetic expression. In a regular expression, a dot (.) is a wildcard that represents any character except the newline. (In awk, dot can even match an embedded newline character.)
Given that we are describing a sequence of characters, the wildcard metacharacter allows you to specify a position that any character can fill.
For instance, if we were searching a file containing a discussion of the Intel family of microprocessors, the following regular expression:
80.86
would match lines containing references to "80286," "80386," or "80486."[3] To match a decimal point or a period, you must escape the dot with a backslash.
[3] The Pentium family of microprocessors breaks our simple pattern-matching experiment, spoiling the fun. Not to mention the original 8086.
It is seldom useful to match just any character at the beginning or end of a pattern. Therefore, the wildcard character is usually preceded and followed by a literal character or other metacharacter. For example, the following regular expression might be written to search for references to chapters:
Chapter.
It searches for "the string `Chapter' followed by any character." In a search, this expression would turn up virtually the same matches as the fixed string pattern "Chapter". Look at the following example:
$ grep 'Chapter.' sample you will find several examples in Chapter 9. "Quote me 'Chapter and Verse'," she said. Chapter Ten
Searching for the string "Chapter" as opposed to "Chapter." would have matched all of the same lines. However, there is one case that would be different - if "Chapter" appeared at the end of a line. The wildcard does not match the newline, so "Chapter." would not match that line, while the fixed-string pattern would match the line.
For all practical purposes, you can rely on a program to produce the correct result. However, that doesn't mean the program always works correctly as far as you are concerned. Most of the time, you can bet that if a program does not produce the output that you expected, the real problem (putting aside input or syntax errors) is how you described what you wanted.
In other words, the place to look to correct the problem is the expression where you described the result you wanted. Either the expression is incomplete or it is improperly formulated. For instance, if a program evaluates this expression:
PAY = WEEKLY_SALARY * 52
and knows the values of these variables, it will calculate the correct result. But someone might object that the formula did not account for salespeople, who also receive a commission. To describe this instance, the expression would need to be reformulated as:
PAY = WEEKLY_SALARY * 52 + COMMISSION
You could say that whoever wrote the first expression did not fully understand the scope of the problem and thus did not describe it well. It is important to know just how detailed a description must be. If you ask someone to bring you a book, and there are multiple books in view, you need to describe more specifically the book that you want (or be content with an indeterminate selection process).
The same is true with regular expressions. A program such as grep is simple and easy to use. Understanding the elements of regular expressions is not so hard, either. Regular expressions allow you to write simple or complex descriptions of patterns. However, what makes writing regular expressions difficult (and interesting) is the complexity of the application: the variety of occurrences or contexts in which a pattern appears. This complexity is inherent in language itself, just as you can't always understand an expression by looking up each word in the dictionary.
The process of writing a regular expression involves three steps:
Knowing what it is you want to match and how it might appear in the text.
Writing a pattern to describe what you want to match.
Testing the pattern to see what it matches.
This process is virtually the same kind of process that a programmer follows to develop a program. Step 1 might be considered the specification, which should reflect an understanding of the problem to be solved as well as how to solve it. Step 2 is analogous to the actual coding of the program, and Step 3 involves running the program and testing it against the specification. Steps 2 and 3 form a loop that is repeated until the program works satisfactorily.
Testing your description of what you want to match ensures that the description works as expected. It usually uncovers a few surprises. Carefully examining the results of a test, comparing the output against the input, will greatly improve your understanding of regular expressions. You might consider evaluating the results of a pattern matching-operation as follows:
The lines that I wanted to match.
The lines that I didn't want to match.
The lines that I didn't match but wanted to match.
The lines that I matched but didn't want to match.
Trying to perfect your description of a pattern is something that you work at from opposite ends: you try to eliminate the false alarms by limiting the possible matches and you try to capture the omissions by expanding the possible matches.
The difficulty is especially apparent when you must describe patterns using fixed strings. Each character you remove from the fixed-string pattern increases the number of possible matches. For instance, while searching for the string "what," you determine that you'd like to match "What" as well. The only fixed-string pattern that will match "What" and "what" is "hat," the longest string common to both. It is obvious, though, that searching for "hat" will produce unwanted matches. Each character you add to a fixed-string pattern decreases the number of possible matches. The string "them" will usually produce fewer matches than the string "the."
Using metacharacters in patterns provides greater flexibility in extending or narrowing the range of matches. Metacharacters, used in combination with literals or other metacharacters, can be used to expand the range of matches while still eliminating the matches that you do not want.
A character class is a refinement of the wildcard concept. Instead of matching any character at a specific position, we can list the characters to be matched. The square bracket metacharacters ([]) enclose the list of characters, any of which can occupy a single position.
Character classes are useful for dealing with uppercase and lowercase letters, for instance. If "what" might appear with either an initial capital letter or a lowercase letter, you can specify:
[Ww]hat
This regular expression can match "what" or "What." It will match any line that contains this four-character string, the first character of which is either "W" or "w." Therefore, it could match "Whatever" or "somewhat."
If a file contained structured heading macros, such as .H1, .H2, .H3, etc., you could extract any of these lines with the regular expression:
\.H[12345]
This pattern matches a three-character string, where the last character is any number from 1 to 5.
The same syntax is used by the UNIX shell. Thus, you can use character classes to specify filenames in UNIX commands. For example, to extract headings from a group of chapter files, you might enter:
$ grep '\.H[123]' ch0[12] ch01:.H1 "Contents of Distribution Tape" ch01:.H1 "Installing the Software" ch01:.H1 "Configuring the System" ch01:.H2 "Specifying Input Devices" ch01:.H3 "Using the Touch Screen" ch01:.H3 "Using the Mouse" ch01:.H2 "Specifying Printers" ch02:.H1 "Getting Started" ch02:.H2 "A Quick Tour" . . .
Note that you have to quote the pattern so that it is passed on to grep rather than interpreted by the shell. The output produced by grep identifies the name of the file for each line printed. As another example of a character class, assume you want to specify the different punctuation marks that end a sentence:
.[!?;:,".].
This expression matches "any character followed by an exclamation mark or question mark or semicolon or colon or comma or quotation mark or period and then followed by two spaces and any character." It could be used to find places where two spaces had been left between the end of a sentence and the beginning of the next sentence, when this occurs on one line. Notice that there are three dots in this expression. The first and last dots are wildcard metacharacters, but the second dot is interpreted literally. Inside square brackets, the standard metacharacters lose their meaning. Thus, the dot inside the square brackets indicates a period. Table 3.2 lists the characters that have a special meaning inside square brackets.
| Character | Function |
|---|---|
| \ | Escapes any special character (awk only) |
| - | Indicates a range when not in the first or last position. |
| ^ | Indicates a reverse match only when in the first position. |
The backslash is special only in awk, making it possible to write "[a\]1]" for a character class that will match an a, a right bracket, or a 1.
The hyphen character (-) allows you to specify a range of characters. For instance, the range of all uppercase English letters[4] can be specified as:
[4] This can actually be very messy when working in non-ASCII character sets and/or languages other than English. The POSIX standard addresses this issue; the new POSIX features are presented below.
[A-Z]
A range of single-digit numbers can be specified as:
[0-9]
This character class helps solve an earlier problem of matching chapter references. Look at the following regular expression:
[cC]hapter [1-9]
It matches the string "chapter" or "Chapter" followed by a space and then followed by any single-digit number from 1 to 9. Each of the following lines match the pattern:
you will find the information in chapter 9 and chapter 12. Chapter 4 contains a summary at the end.
Depending upon the task, the second line in this example might be considered a false alarm. You might add a space following "[1-9]" to avoid matching two-digit numbers. You could also specify a class of characters not to be matched at that position, as we'll see in the next section. Multiple ranges can be specified as well as intermixed with literal characters:
[0-9a-z?,.;:'"]
This expression will match "any single character that is numeric, lowercase alphabetic, or a question mark, comma, period, semicolon, colon, single quote, or quotation mark." Remember that each character class matches a single character. If you specify multiple classes, you are describing multiple consecutive characters such as:
[a-zA-Z][.?!]
This expression will match "any lowercase or uppercase letter followed by either a period, a question mark, or an exclamation mark."
The close bracket (]) is interpreted as a member of the class if it occurs as the first character in the class (or as the first character after a circumflex; see the next section). The hyphen loses its special meaning within a class if it is the first or last character. Therefore, to match arithmetic operators, we put the hyphen (-) first in the following example:
[-+*/]
In awk, you could also use the backslash to escape the hyphen or close bracket wherever either one occurs in the range, but the syntax is messier.
Trying to match dates with a regular expression is an interesting problem. Here are two possible formats:
MM-DD-YY MM/DD/YY
The following regular expression indicates the possible range of values for each character position:
[0-1][0-9][-/][0-3][0-9][-/][0-9][0-9]
Either "-" or "/" could be the delimiter. Putting the hyphen in the first position ensures that it will be interpreted in a character class literally, as a hyphen, and not as indicating a range.[5]
[5] Note that the expression matches dates that mix their delimiters, as well as impossible dates like "15/32/78."
Normally, a character class includes all the characters that you want to match at that position. The circumflex (^) as the first character in the class excludes all of the characters in the class from being matched. Instead any character except newline[6] that is not listed in the square brackets will be matched. The following pattern will match any non-numeric character:
[6] In awk, newline can also be matched.
[^0-9]
It matches all uppercase and lowercase letters of the alphabet and all special characters such as punctuation marks.
Excluding specific characters is sometimes more convenient than explicitly listing all the characters you want to match. For instance, if you wanted to match any consonant, you could simply exclude vowels:
[^aeiou]
This expression would match any consonant, any vowel in uppercase, and any punctuation mark or special character.
Look at the following regular expression:
\.DS "[^1]"
This expression matches the string ".DS" followed by a space, a quote followed by any character other than the number "1," followed by a quote.[7] It is designed to avoid matching the following line:
[7] When typing this pattern at the command line, be sure to enclose it in single quotes. The ^ is special to the original Bourne shell.
.DS "1"
while matching lines such as:
.DS "I" .DS "2"
This syntax can also be used to limit the extent of a match, as we'll see up ahead.
The POSIX standard formalizes the meaning of regular expression characters and operators. The standard defines two classes of regular expressions: Basic Regular Expressions (BREs), which are the kind used by grep and sed, and Extended Regular Expressions, which are the kind used by egrep and awk.
In order to accommodate non-English environments, the POSIX standard enhanced the ability of character classes to match characters not in the English alphabet. For example, the French è is an alphabetic character, but the typical character class [a-z] would not match it. Additionally, the standard provides for sequences of characters that should be treated as a single unit when matching and collating (sorting) string data.
POSIX also changed what had been common terminology. What we've been calling a "character class" is called a "bracket expression" in the POSIX standard. Within bracket expressions, beside literal characters such as a, !, and so on, you can have additional components. These are:
Character classes. A POSIX character class consists of keywords bracketed by [: and :]. The keywords describe different classes of characters such as alphabetic characters, control characters, and so on (see Table 3.3).
Collating symbols. A collating symbol is a multicharacter sequence that should be treated as a unit. It consists of the characters bracketed by [. and .].
Equivalence classes. An equivalence class lists a set of characters that should be considered equivalent, such as e and è. It consists of a named element from the locale, bracketed by [= and =].
All three of these constructs must appear inside the square brackets of a bracket expression. For example [[:alpha:]!] matches any single alphabetic character or the exclamation point, [[.ch.]] matches the collating element ch, but does not match just the letter c or the letter h. In a French locale, [[=e=]] might match any of e, è, or é. Classes and matching characters are shown in Table 3.3.
| Class | Matching Characters |
|---|---|
| [:alnum:] | Printable characters (includes whitespace) |
| [:alpha:] | Alphabetic characters |
| [:blank:] | Space and tab characters |
| [:cntrl:] | Control characters |
| [:digit:] | Numeric characters |
| [:graph:] | Printable and visible (non-space) characters |
| [:lower:] | Lowercase characters |
| [:print:] | Alphanumeric characters |
| [:punct:] | Punctuation characters |
| [:space:] | Whitespace characters |
| [:upper:] | Uppercase characters |
| [:xdigit:] | Hexadecimal digits |
These features are slowly making their way into commercial versions of sed and awk, as vendors fully implement the POSIX standard. GNU awk and GNU sed support the character class notation, but not the other two bracket notations. Check your local system documentation to see if they are available to you.
Because these features are not widely available yet, the scripts in this book will not rely on them, and we will continue to use the term "character class" to refer to lists of characters in square brackets.
The asterisk (*) metacharacter indicates that the preceding regular expression may occur zero or more times. That is, if it modifies a single character, the character may be there or not, and if it is, there may be more than one of them. You could use the asterisk metacharacter to match a word that might appear in quotes.
"*hypertext"*
The word "hypertext" will be matched regardless of whether it appears in quotes or not.
Also, if the literal character modified by the asterisk does exist, there could be more than one occurrence. For instance, let's examine a series of numbers:
1 5 10 50<PHONE_NUMBER> 5000
The regular expression
[15]0*
would match all lines, whereas the regular expression
[15]00*
would match all but the first two lines. The first zero is a literal, but the second is modified by the asterisk, meaning it might or might not be present. A similar technique is used to match consecutive spaces because you usually want to match one or more, not zero or more, spaces. You can use the following to do that:
*
When preceded by a dot metacharacter, the asterisk metacharacter matches any number of characters. It can be used to identify a span of characters between two fixed strings. If you wanted to match any string inside of quotation marks, you could specify:
".*"
This would match all characters between the first and last quotation marks on the line plus the quotation marks. The span matched by ".*" is always the longest possible. This may not seem important now but it will be once you learn about replacing the string that was matched.
As another example, a pair of angle brackets is a common notation for enclosing formatting instructions used in markup languages, such as SGML, HTML, and Ventura Publisher.
You could print all lines with these marks by specifying:
$grep '<.*>' sample
When used to modify a character class, the asterisk can match any number of a character in that class. For instance, look at the following five-line sample file:
I can do it I cannot do it I can not do it I can't do it I cant do it
If we wanted to match each form of the negative statement, but not the positive statement, the following regular expression would do it:
can[no']*t
The asterisk causes any of the characters in the class to be matched in any order and for any number of occurrences. Here it is:
$grep "can[no']*t" sample
I cannot do it I can not do it I can't do it I cant do it
There are four hits and one miss, the positive statement. Notice that had the regular expression tried to match any number of characters between the string "can" and "t," as in the following example:
can.*t
it would have matched all lines.
The ability to match "zero or more" of something is known by the technical term "closure." The extended set of metacharacters used by egrep and awk provides several variations of closure that can be quite useful. The plus sign (+) matches one or more occurrences of the preceding regular expression. Our earlier example of matching one or more spaces can be simplified as such:
+
The plus sign metacharacter can be thought of as "at least one" of the
preceding character. In fact, it better corresponds to how many people
think *
works.
The question mark
(?
) matches zero or one occurrences.
For instance, in a previous example, we used a regular
expression to match "80286," "80386," and "80486."
If we wanted to also match the string "8086,"
we could write a regular expression that could be
used with egrep or awk:
80[234]?86
It matches the string "80" followed by a "2," a "3," a "4," or no
character followed by the string "86."
Don't confuse the ?
in a regular expression with the ?
wildcard in the
shell. The shell's ?
represents a single character, equivalent to .
in a
regular expression.
As you have probably figured out, it is sometimes difficult to match a complete word. For instance, if we wanted to match the pattern "book," our search would hit lines containing the word "book" and "books" but also the words "bookish," "handbook," and "booky." The obvious thing to do to limit the matching is to surround "book" with spaces.
book
However, this expression would only match the word "book"; it would miss the plural "books". To match either the singular or plural word, you could use the asterisk metacharacter:
books*
This will match "book" or "books". However, it will not match "book" if it is followed by a period, a comma, a question mark, or a quotation mark.
When you combine the asterisk with the wildcard metacharacter (.), you can match zero or more occurrences of any character. In the previous example, we might write a fuller regular expression as:
book.*
This expression matches the string "book" followed by "any number of characters or none followed by a space." Here are a few lines that would match:
Here are the books that you requested Yes, it is a good book for children It is amazing to think that it was called a "harmful book" when once you get to the end of the book, you can't believe
(Note that only the second line would be matched by the fixed string "book".) The expression "book.*" matches lines containing words such as "booky," "bookworm," and "bookish." We could eliminate two of these matches by using a different modifier. The question mark (?), which is part of the extended set of metacharacters, matches 0 or 1 occurrences of the preceding character. Thus, the expression:
book.?
would match "book," "books," and "booky" but not "bookish" and "bookworm." To eliminate a word like "booky," we would have to use character classes to specify all the characters in that position that we want to match. Furthermore, since the question mark metacharacter is not available with sed, we would have to resort to character classes anyway, as you'll see later on.
Trying to be all-inclusive is not always practical with a regular expression, especially when using grep. Sometimes it is best to keep the expression simple and allow for the misses. However, as you use regular expressions in sed for making replacements, you will need to be more careful that your regular expression is complete. We will look at a more comprehensive regular expression for searching for words in Part II of "What's the Word?" later in this chapter.
There are two metacharacters that allow you to specify the context in which a string appears, either at the beginning of a line or at the end of a line. The circumflex (^) metacharacter is a single-character regular expression indicating the beginning of a line. The dollar sign ($) metacharacter is a single-character regular expression indicating the end of a line. These are often referred to as "anchors," since they anchor, or restrict, the match to a specific position. You could print lines that begin with a tab:
^
(The represents a literal tab character, which is normally invisible.) Without the ^ metacharacter, this expression would print any line containing a tab.
Normally, using vi to input text to be processed by troff, you do not want spaces appearing at the end of lines. If you want to find (and remove) them, this regular expression will match lines with one or more spaces at the end of a line:
*$
troff requests and macros must be input at the beginning of a line. They are two-character strings, preceded by a dot. If a request or macro has an argument, it is usually followed by a space. The regular expression used to search for such requests is:
^\...
This expression matches "a dot at the beginning of a line followed by any two-character string, and then followed by a space."
You can use both positional metacharacters together to match blank lines:
^$
You might use this pattern to count the number of blank lines in a file using the count option, -c, to grep:
$grep -c '^$' ch04
5
This regular expression is useful if you want to delete blank lines using sed. The following regular expression can be used to match a blank line even if it contains spaces:
^*$
Similarly, you can match the entire line:
^.*$
which is something you might possibly want to do with sed.
In sed (and grep), "^" and "$" are only special when they occur at the beginning or end of a regular expression, respectively. Thus "^abc" means "match the letters a, b, and c only at the beginning of the line," while "ab^c" means "match a, b, a literal ^, and then c, anywhere on the line." The same is true for the "$."
In awk, it's different; "^" and "$" are always special, even though it then becomes possible to write regular expressions that don't match anything. Suffice it to say that in awk, when you want to match either a literal "^" or "$," you should always escape it with a backslash, no matter what its position in the regular expression.
A pattern-matching program such as grep does not match a string if it extends over two lines. For all practical purposes, it is difficult to match phrases with assurance. Remember that text files are basically unstructured and line breaks are quite random. If you are looking for any sequence of words, it is possible that they might appear on one line but they may be split up over two.
You can write a series of regular expression to capture a phrase:
Almond Joy Almond$ ^Joy
This is not perfect, as the second regular expression will match "Almond" at the end of a line, regardless of whether or not the next line begins with "Joy". A similar problem exists with the third regular expression.
Later, when we look at sed, you'll learn how to match patterns over multiple lines and you'll see a shell script incorporating sed that makes this capability available in a general way.
The metacharacters that allow you to specify repeated occurrences of a character (*+?) indicate a span of undetermined length. Consider the following expression:
11*0
It will match each of the following lines:
10 110<PHONE_NUMBER>111111111111111111111110
These metacharacters give elasticity to a regular expression.
Now let's look at a pair of metacharacters that allow you to indicate a span and also determine the length of the span. So, you can specify the minimum and maximum number of occurrences of a literal character or regular expression.
\{ and \} are available in grep and sed.[8] POSIX egrep and POSIX awk use { and }. In any case, the braces enclose one or two arguments.
[8] Very old versions may not have them; Caveat emptor.
\{n,m\}
n and m are integers between 0 and 255. If you specify \{n\} by itself, then exactly n occurrences of the preceding character or regular expression will be matched. If you specify \{n,\}, then at least n occurrences will be matched. If you specify \{n,m\}, then any number of occurrences between n and m will be matched.[9]
[9] Note that "?" is equivalent to "\{0,1\}", "*" is equivalent to "\{0,\}", "+" is equivalent to "\{1,\}", and no modifier is equivalent to "\{1\}".
For example, the following expression will match "1001," "10001," and "100001" but not "101" or "1000001":
10\{2,4\}1
This metacharacter pair can be useful for matching data in fixed-length fields, data that perhaps was extracted from a database. It can also be used to match formatted data such as phone numbers, U.S. social security numbers, inventory part IDs, etc. For instance, the format of a social security number is three digits, a hyphen, followed by two digits, a hyphen, and then four digits. That pattern could be described as follows:
[0-9]\{3\}-[0-9]\{2\}-[0-9]\{4\}
Similarly, a North American local phone number could be described with the following regular expression:
[0-9]\{3\}-[0-9]\{4\}
If you are using pre-POSIX awk, where you do not have braces available, you can simply repeat the character classes the appropriate number of times:
[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]
The vertical bar (|) metacharacter, part of the extended set of metacharacters, allows you to specify a union of regular expressions. A line will match the pattern if it matches one of the regular expressions. For instance, this regular expression:
UNIX|LINUX
will match lines containing either the string "UNIX" or the string "LINUX". More than one alternative can be specified:
UNIX|LINUX|NETBSD
A line matching any of these three patterns will be printed by egrep.
In sed, lacking the union metacharacter, you would specify each pattern separately. In the next section, where we look at grouping operations, we will see additional examples of this metacharacter.
Parentheses, (), are used to group regular expressions and establish precedence. They are part of the extended set of metacharacters. Let's say that a company's name in a text file is referred to as "BigOne" or "BigOne Computer":
BigOne(Computer)?
This expression will match the string "BigOne" by itself or followed by a single occurrence of the string "Computer". Similarly, if a term is sometime spelled out and at other times abbreviated:
$egrep "Lab(oratorie)?s" mail.list
Bell Laboratories, Lucent Technologies Bell Labs
You can use parentheses with a vertical bar to group alternative operations. In the following example, we use it to specify a match of the singular or plural of the word "company."
compan(y|ies)
It is important to note that applying a quantifier to a parenthesized group of characters can't be done in most versions of sed and grep, but is available in all versions of egrep and awk.
Let's reevaluate the regular expression for searching for a single word in light of the new metacharacters we've discussed. Our first attempt at writing a regular expression for grep to search for a word concluded with the following expression:
book.*
This expression is fairly simple, matching a space followed by the string "book" followed by any number of characters followed by a space. However, it does not match all possible occurrences and it does match a few nuisance words.
The following test file contains numerous occurrences of "book." We've added a notation, which is not part of the file, to indicate whether the input line should be a "hit" (>) and included in the output or a "miss" (<). We've tried to include as many different examples as possible.
$cat bookwords
> This file tests for book in various places, such as > book at the beginning of a line or > at the end of a line book > as well as the plural books and < handbooks. Here are some < phrases that use the word in different ways: > "book of the year award" > to look for a line with the word "book" > A GREAT book! > A great book? No. > told them about (the books) until it > Here are the books that you requested > Yes, it is a good book for children > amazing that it was called a "harmful book" when > once you get to the end of the book, you can't believe < A well-written regular expression should < avoid matching unrelated words, < such as booky (is that a word?) < and bookish and < bookworm and so on.
As we search for occurrences of the word "book," there are 13 lines that should be matched and 7 lines that should not be matched. First, let's run the previous regular expression on the sample file and check the results.
$grep 'book.*' bookwords
This file tests for book in various places, such as as well as the plural books and A great book? No. told them about (the books) until it Here are the books that you requested Yes, it is a good book for children amazing that it was called a "harmful book" when once you get to the end of the book, you can't believe such as booky (is that a word?) and bookish and
It only prints 8 of the 13 lines that we want to match and it prints 2 of the lines that we don't want to match. The expression matches lines containing the words "booky" and "bookish." It ignores "book" at the beginning of a line and at the end of a line. It ignores "book" when there are certain punctuation marks involved.
To restrict the search even more, we must use character classes. Generally, the list of characters that might end a word are punctuation marks, such as:
? . , ! ; : '
In addition, quotation marks, parentheses, braces, and brackets might surround a word or open or close with a word:
" () {} []
You would also have to accommodate the plural or possessive forms of the word.
Thus, you would have two different character classes: before and after the word. Remember that all we have to do is list the members of the class inside square brackets. Before the word, we now have:
["[{(]
and after the word:
[]})"?!.,;:'s]
Note that putting the closing square bracket as the first character in the class makes it a member of the class rather than closing the set. Putting the two classes together, we get the expression:
["[{(]*book[]})"?!.,;:'s]*
Show this to the uninitiated, and they'll throw up their hands in despair! But now that you know the principles involved, you can not only understand this expression, but could easily reconstruct it. Let's see how it does on the sample file (we use double quotes to enclose the single quote character, and then a backslash in front of the embedded double quotes):
$grep " [\"[{(]*book[]})\"?!.,;:'s]* " bookwords
This file tests for book in various places, such as as well as the plural books and A great book? No. told them about (the books) until it Here are the books that you requested Yes, it is a good book for children amazing that it was called a "harmful book" when once you get to the end of the book, you can't believe
We eliminated the lines that we don't want but there are four lines that we're not getting. Let's examine the four lines:
book at the beginning of a line or at the end of a line book "book of the year award" A GREAT book!
All of these are problems caused by the string appearing at the beginning or end of a line. Because there is no space at the beginning or end of a line, the pattern is not matched. We can use the positional metacharacters, ^ and $. Since we want to match either a space or beginning or end of a line, we can use egrep and specify the "or" metacharacter along with parentheses for grouping. For instance, to match either the beginning of a line or a space, you could write the expression:
(^| )
(Because | and () are part of the extended set of metacharacters, if you were using sed, you'd have to write different expressions to handle each case.)
Here's the revised regular expression:
(^| )["[{(]*book[]})"?\!.,;:'s]*( |$)
Now let's see how it works:
$egrep "(^| )[\"[{(]*book[]})\"?\!.,;:'s]*( |$)" bookwords
This file tests for book in various places, such as book at the beginning of a line or at the end of a line book as well as the plural books and "book of the year award" to look for a line with the word "book" A GREAT book! A great book? No. told them about (the books) until it Here are the books that you requested Yes, it is a good book for children amazing that it was called a "harmful book" when once you get to the end of the book, you can't believe
This is certainly a complex regular expression; however, it can be broken down into parts. This expression may not match every single instance, but it can be easily adapted to handle other occurrences that you may find.
You could also create a simple shell script to replace "book" with a command-line argument. The only problem might be that the plural of some words is not simply "s." By sleight of hand, you could handle the "es" plural by adding "e" to the character class following the word; it would work in many cases.
As a further note, the ex and vi text editors have a special metacharacter for matching a string at the beginning of a word, \<, and one for matching a string at the end of a word, \>. Used as a pair, they can match a string only when it is a complete word. (For these operators, a word is a string of non-whitespace characters with whitespace on both sides, or at the beginning or end of a line.) Matching a word is such a common case that these metacharacters would be widely used, if they were available for all regular expressions.[10]
[10] GNU programs, such as the GNU versions of awk, sed, and grep, also support \< and \>.
When using grep, it seldom matters how you match the line as long as you match it. When you want to make a replacement, however, you have to consider the extent of the match. So, what characters on the line did you actually match?
In this section, we're going to look at several examples that demonstrate the extent of a match. Then we'll use a program that works like grep but also allows you to specify a replacement string. Lastly, we will look at several metacharacters used to describe the replacement string.
Let's look at the following regular expression:
A*Z
This matches "zero or more occurrences of A followed by Z." It will produce the same result as simply specifying "Z". The letter "A" could be there or not; in fact, the letter "Z" is the only character matched. Here's a sample two-line file:
All of us, including Zippy, our dog Some of us, including Zippy, our dog
If we try to match the previous regular expression, both lines would print out. Interestingly enough, the actual match in both cases is made on the "Z" and only the "Z". We can use the gres command (see the sidebar, "A Program for Making Single Replacements") to demonstrate the extent of the match.
$ gres "A*Z" "00" test
All of us, including 00ippy, our dog Some of us, including 00ippy, our dog
We would have expected the extent of the match on the first line to be from the "A" to the "Z" but only the "Z" is actually matched. This result may be more apparent if we change the regular expression slightly:
A.*Z
".*" can be interpreted as "zero or more occurrences of any character," which means that "any number of characters" can be found, including none at all. The entire expression can be evaluated as "an A followed by any number of characters followed by a Z." An "A" is the initial character in the pattern and "Z" is the last character; anything or nothing might occur in between. Running grep on the same two-line file produces one line of output. We've added a line of carets (^) underneath to mark what was matched.
All of us, including Zippy, our dog ^^^^^^^^^^^^^^^^^^^^^^
The extent of the match is from "A" to "Z". The same regular expression would also match the following line:
I heard it on radio station WVAZ 1060. ^^
The string "A.*Z" matches "A followed by any number of characters (including zero) followed by Z." Now, let's look at a similar set of sample lines that contain multiple occurrences of "A" and "Z".
All of us, including Zippy, our dog All of us, including Zippy and Ziggy All of us, including Zippy and Ziggy and Zelda
The regular expression "A.*Z" will match the longest possible extent in each case.
All of us, including Zippy, our dog ^^^^^^^^^^^^^^^^^^^^^^ All of us, including Zippy and Ziggy ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ All of us, including Zippy and Ziggy and Zelda ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This can cause problems if what you want is to match the shortest extent possible.
Earlier we said that a regular expression tries to match the longest string possible and that can cause unexpected problems. For instance, look at the regular expression to match any number of characters inside of quotation marks:
".*"
Let's look at a troff macro that has two quoted arguments, as shown below:
.Se "Appendix" "Full Program Listings"
To match the first argument, we might describe the pattern with the following regular expression:
\.Se ".*"
However, it ends up matching the whole line because the second quotation mark in the pattern matches the last quotation mark on the line. If you know how many arguments there are, you can specify each of them:
\.Se ".*" ".*"
Although this works as you'd expect, each line might not have the same number of arguments, causing omissions - you simply want the first argument. Here's a different regular expression that matches the shortest possible extent between two quotation marks:
"[^"]*"
It matches "a quote followed by any number of characters that do not match a quote followed by a quote":
$gres '"[^"]*"' '00' sampleLine
.Se 00 "Appendix"
Now let's look at a few lines with a dot character (.) used as a leader between two columns of numbers:
1........5 5........10 10.......20 100......200
The difficulty in matching the leader characters is that their number is variable. Let's say that you wanted to replace all of the leaders with a single tab. You might write a regular expression to match the line as follows:
[0-9][0-9]*\.\.*[0-9][0-9]*
This expression might unexpectedly match the line:
see Section 2.3
To restrict matching, you could specify the minimum number of dots that are common to all lines:
[0-9][0-9]*\.\{5,\}[0-9][0-9]*
This expression uses braces available in sed to match "a single number followed by at least five dots and then followed by a single number." To see this in action, we'll show a sed command that replaces the leader dots with a hyphen. However, we have not covered the syntax of sed's replacement metacharacters - \( and \) to save a part of a regular expression and \1 and \2 to recall the saved portion. This command, therefore, may look rather complex (it is!) but it does the job.
$ sed 's/\([0-9][0-9]*\)\.\{5,\}\([0-9][0-9]*\)/\1-\2/' sample 1-5 5-10 10-20 100-200
A similar expression can be written to match one or more leading tabs or tabs between columns of data. You could change the order of columns as well as replacing the tab with another delimiter. You should experiment on your own by making simple and complex replacements, using sed or gres.


simulation::montecarlo - Monte Carlo simulations
The technique of Monte Carlo simulations is basically simple:
generate random values for one or more parameters.
evaluate the model of some system you are interested in and record the interesting results for each realisation of these parameters.
after a suitable number of such trials, deduce an overall characteristic of the model.
You can think of a model of a network of computers, an ecosystem of some kind or in fact anything that can be quantitatively described and has some stochastic element in it.
The package simulation::montecarlo offers a basic framework for such a modelling technique:
# # MC experiments: # Determine the mean and median of a set of points and compare them # ::simulation::montecarlo::singleExperiment -init { package require math::statistics set prng [::simulation::random::prng_Normal 0.0 1.0] } -loop { set numbers {} for { set i 0 } { $i < [getOption samples] } { incr i } { lappend numbers [$prng] } set mean [::math::statistics::mean $numbers] set median [::math::statistics::median $numbers] ;# ? Exists? setTrialResult [list $mean $median] } -final { set result [getTrialResults] set means {} set medians {} foreach r $result { foreach {m M} $r break lappend means $m lappend medians $M } puts [getOption reportfile] "Correlation: [::math::statistics::corr $means $medians]" } -trials 100 -samples 10 -verbose 1 -columns {Mean Median}
This example attemps to find out how well the median value and the mean value of a random set of numbers correlate. Sometimes a median value is a more robust characteristic than a mean value - especially if you have a statistical distribution with "fat" tails.
The package defines the following auxiliary procedures:
Get the value of an option given as part of the singleExperiment command.
Given keyword (without leading minus)
Returns 1 if the option is available, 0 if not.
Given keyword (without leading minus)
Set the value of the given option.
Given keyword (without leading minus)
(New) value for the option
Store the results of the trial for later analysis
List of values to be stored
Set the results of the entire experiment (typically used in the final phase).
List of values to be stored
Get the results of all individual trials for analysis (typically used in the final phase or after completion of the command).
Get the results of the entire experiment (typically used in the final phase or even after completion of the singleExperiment command).
Interchange columns and rows of a list of lists and return the result.
List of lists of values
There are two main procedures: integral2D and singleExperiment.
Integrate a function over a two-dimensional region using a Monte Carlo approach.
Arguments PM
Iterate code over a number of trials and store the results. The iteration is gouverned by parameters given via a list of keyword-value pairs.
List of keyword-value pairs, all of which are available during the execution via the getOption command.
The singleExperiment command predefines the following options:
-init code: code to be run at start up
-loop body: body of code that defines the computation to be run time and again. The code should use setTrialResult to store the results of each trial (typically a list of numbers, but the interpretation is up to the implementation). Note: Required keyword.
-final code: code to be run at the end
-trials n: number of trials in the experiment (required)
-reportfile file: opened file to send the output to (default: stdout)
-verbose: write the intermediate results (1) or not (0) (default: 0)
-analysis proc: either "none" (no automatic analysis), standard (basic statistics of the trial results and a correlation matrix) or the name of a procedure that will take care of the analysis.
-columns list: list of column names, useful for verbose output and the analysis
Any other options can be used via the getOption procedure in the body.
The procedure singleExperiment works by constructing a temporary procedure that does the actual work. It loops for the given number of trials.
As it constructs a temporary procedure, local variables defined at the start continue to exist in the loop.
Mathematics
Copyright © 2008 Arjen Markus <arjenmarkus@users.sourceforge.net>


Plugin Information |
|---|
View URL SCM on the plugin site for more information. |
This plugin allows the use of URLs as an SCM.
This is an SCM plugin for Jenkins. While URLs are not actually a proper SCM, the two main behaviors of an SCM are supported - checkout and polling. Polling is accomplished by checking the last-modified property of the URL. Checkout is accomplished by copying the content of the URL into the workspace as a file. The file is given the same name as the final filename component of the URL. URLs without a filename component cannot be used at this time.
This does duplicate some of what the URLChange Trigger plugin does.
Benefits this plugin over the URLChange Trigger are:
1. You can choose your own polling schedule via the SCM Polling trigger.
2. Less resource intensive polling mechanism, since checking last-modified requires few bytes to transfer, regardless of the amount of data in the URL.
Benefits of URLChange Trigger over this plugin:
1. Jenkins only supports one SCM plugin per project. If you want to trigger an SCM checkout via a URL, then URLChange Trigger is a better choice.
2. The last-modified property of a URL is not the right trigger for your builds, instead you need the content of the URL to change to trigger a build.
Change Log
Version 1.6 (Nov 2, 2011)
- JENKINS-11572
Version 1.5 (Jan 27, 2010)
- Update code for more recent Hudson


Use the form below to add or remove data analysis and visualization tools to your notebook.
These tools will analyze the selected dataset and embed interactive results in your notebook.
Once you have selected the desired tools, click Continue to proceed.


Voters today are embracing presidential candidates who appeal to their specific passions and ideals much like they only trust news sources that align with their ideological views.
Our ability to self-select our newsfeed via Facebook, Twitter and even whether our main source of news is Nation Media or Citizen is creating an echo chamber for voters.
I’d like to write a piece explaining how climate change could completely wreck winemaking as we know it, and even render certain varietals and blends impossible to create should temperatures rise too far. I would briefly explain how varietal characteristics depend on terroir — which, in turn, is defined in part by climate — before imagining how certain varietals’ expressions might change should temperatures reliably increase by even just a few degrees.
A few years ago, statement necklaces became a professional crutch for me. When I made the switch from journalism to PR, I felt like the shlubby and out-of-place little sister who walked in on a party of much cooler, older, prettier high school girls. I moved from my job at a local newspaper in Iowa to a PR job in a bigger city, and overnight I became hyper-aware of my dress pants that were too uptight and my Target basics that were too, well, basic. Every woman working at an agency in town seemed to own the same variation of that chunky J. Crew statement necklace, so I went out and bought one of my own (a much cheaper version at Charming Charlie’s, but it was the gateway necklace). Years later, I’m still working in PR, but I’ve settled into my own style and I don’t feel the need to cling to costume jewelry to fit in. And now I’ve got all these damn statement necklaces that aren’t my style at all.


In 2015, 90% of all Americans
owned a cell phone.
Previous researchers have used GPS to track participant movement. However, GPS cannot track movement indoors.
Social support in college leads to increased mental health, decreased stress levels, and overall wellbeing.
WiFi can be used to track participant location, but new apps and testing need to be done.
Participants were asked to use Android smartphones preinstalled with our software that could record and send
phone usage data and colocation
information to our server located in the university.
The software application ran on any android mobile phone, and would automatically start at bootup.
We used the WiFi fingerprinting method for indoor localization, which achieved an accuracy of 5-7 meters in our study.
We also implemented periodic Bluetooth scanning to discover participants that were close to each other.
This study followed participants for one academic year.
Participants were also asked to complete self-reported questionnaires on language use,
friendship tie-strength, and adaptation to college life, once each term (~every 13 weeks).


{% extends "_base.html" %} {% block meta_title %}Financial Assistance at PyCon CZ 2016{% endblock %} {% block content %}
Our primary goal is to make PyCon CZ accessible to everyone, irrespective of their financial situation. For this reason, we provide multiple tiers of ticket prices, Early-Bird, Student, Individual and Corporate. This is based on the principle that those who can afford to pay for tickets subsidize those who cannot. This structure enables us to include major diversity and outreach programmes such as DjangoGirls, reward and encourage active participation in the PyCon CZ event organization, and fund PyCon CZ’s Financial Aid programme.
PyCon CZ’s financial aid programme aims to provide funds to help people attend PyCon CZ. Financial aid recipients have some part of their expenses (which may include travel, accommodation, or ticket registration) paid for by the PyCon CZ budget. We actively encourage people to apply for financial aid. While we can't cover all expenses for everyone, we try our best to optimally allocate our budget. Optimal is, of course, an ambiguous property.
Since PyCon is a well positioned international Python conference in central Europe, it's a meeting place for Python developers from all around the globe. Therefore, the process is designed to benefit people that we believe make PyCon CZ better, particularly speakers and workshop tutors, as well as notable open source contributors.
This way, the process attempts to promote a more diverse community event.
Finally, the process tries to help people with relatively lower incomes, be it because of their location (lower income countries) or their profession (such as students, or the unemployed).
In short, we use the financial aid budget to help individuals who would otherwise not be able to attend the conference or whose presence will bring a justifiably positive impact for other attendees.
The financial aid programme supports the community by making it more accessible at PyCon CZ. It is true to the spirit of PyCon to make the information and interactions available to everyone.
PyCon CZ aims to be the largest annual gathering for the Python community in the Czech Republic, focused on honoring and supporting awesome people teaching, learning and innovating with Python in the Czech Republic and surrounding countries. The Python Software Foundation, the parent PyCon event organizer and sponsor, aims to promote, protect, and advance the Python programming language, and to support and facilitate the growth of a diverse and international community of Python programmers. We believe that the financial aid programme is perfectly aligned with these goals.
To submit a financial aid application, sign up or log in to your account and proceed to the Financial Aid section of your account dashboard.
Note well that our Code of Conduct is strictly enforced during all official PyCon CZ event activities. All recipients of financial aid cited for a CoC violations will be immediately disqualified for all funding awards.
Please do not hesitate to email us at info@pycon.cz


Sign in to access our organised network of courseware which will not only prepare you for ICSE but will equip you with a real world learning experience
Learn more
A website built by Rishav Kundu and Rudradev Roy


– layout: post title: “New Years Head Start” date: 2014-04-30 —
I figured it be a lot easier to keep a New Years resolution about blogging, reflecting, and sharing, if I actually started the year off with a blog. ;) Neat thing about it - powered by Jekyll and I can use Markdown to author my posts. It actually is a lot easier than I thought it was going to be.


Public Member Functions | |
Constructors | |
| XSAttributeUse (XSAttributeDeclaration *const xsAttDecl, XSModel *const xsModel, MemoryManager *const manager=XMLPlatformUtils::fgMemoryManager) | |
| The default constructor. | |
Destructor | |
| ~XSAttributeUse () | |
XSAttributeUse methods | |
| bool | getRequired () const |
| [required]: determines whether this use of an attribute declaration requires an appropriate attribute information item to be present, or merely allows it. | |
| XSAttributeDeclaration * | getAttrDeclaration () const |
| [attribute declaration]: provides the attribute declaration itself, which will in turn determine the simple type definition used. | |
| XSConstants::VALUE_CONSTRAINT | getConstraintType () const |
| Value Constraint: one of default, fixed. | |
| const XMLCh * | getConstraintValue () |
| Value Constraint: The actual value. | |
Protected Attributes | |
| bool | fRequired |
| XSConstants::VALUE_CONSTRAINT | fConstraintType |
| const XMLCh * | fConstraintValue |
| XSAttributeDeclaration * | fXSAttributeDeclaration |
Friends | |
| class | XSObjectFactory |
| XSAttributeUse::XSAttributeUse | ( | XSAttributeDeclaration *const | xsAttDecl, | |
| XSModel *const | xsModel, | |||
| MemoryManager *const | manager = XMLPlatformUtils::fgMemoryManager | |||
| ) |
The default constructor.
| xsAttDecl | ||
| xsModel | ||
| manager | The configurable memory manager |
| XSAttributeUse::~XSAttributeUse | ( | ) |
| bool XSAttributeUse::getRequired | ( | ) | const |
[required]: determines whether this use of an attribute declaration requires an appropriate attribute information item to be present, or merely allows it.
References fRequired.
| XSAttributeDeclaration * XSAttributeUse::getAttrDeclaration | ( | ) | const |
[attribute declaration]: provides the attribute declaration itself, which will in turn determine the simple type definition used.
References fXSAttributeDeclaration.
| XSConstants::VALUE_CONSTRAINT XSAttributeUse::getConstraintType | ( | ) | const |
| const XMLCh * XSAttributeUse::getConstraintValue | ( | ) |
friend class XSObjectFactory [friend] |
bool XSAttributeUse::fRequired [protected] |
Referenced by getRequired().
Referenced by getConstraintType().
const XMLCh* XSAttributeUse::fConstraintValue [protected] |
Referenced by getConstraintValue().
Referenced by getAttrDeclaration().


assigned
by None at 2020-02-14 12:59:35.referenced
by None at 2020-02-14 20:17:24.referenced
by None at 2020-02-14 20:19:11.I'm not really sure this is a good idea. If the department head makes the changes how will we guarantee the person taking the trip will understand they are not getting money for food, ect.
I agree with @carolyncole . We did take this into consideration and decided it would be best if the approver requests specific changes (there is in fact a "notes" field for this).
We did discuss putting something prominent on the show screen and in the email that explains what is covered and what isn't based on the type of travel assigned, but I don't think we have a ticket for that yet. I think that would be a good idea since the travel policy is not easy to parse the way it's written.
mentioned
by None at 2020-02-14 13:49:19.subscribed
by None at 2020-02-14 13:49:19.referenced
by None at 2020-02-14 12:55:40.assigned
by None at 2020-02-14 12:58:09.referenced
by None at 2020-02-14 12:59:51.closed
by Axa Mei Liauw at 2020-02-14 14:30:07.head_ref_force_pushed
by None at 2020-02-14 12:59:51.referenced
by Axa Mei Liauw at 2020-02-14 14:30:07.merged
by Axa Mei Liauw at 2020-02-14 14:30:07.closed
by Axa Mei Liauw at 2020-02-14 14:30:07.head_ref_deleted
by Axa Mei Liauw at 2020-02-14 14:30:10.referenced
by Axa Mei Liauw at 2020-02-14 15:32:48.merged
by Axa Mei Liauw at 2020-02-14 15:32:49.closed
by Axa Mei Liauw at 2020-02-14 15:32:49.head_ref_deleted
by Axa Mei Liauw at 2020-02-14 15:32:53.referenced
by Axa Mei Liauw at 2020-02-14 15:37:55.merged
by Axa Mei Liauw at 2020-02-14 15:37:55.closed
by Axa Mei Liauw at 2020-02-14 15:37:56.head_ref_deleted
by Axa Mei Liauw at 2020-02-14 15:38:01.review_requested
by None at 2020-02-14 20:57:25.referenced
by Axa Mei Liauw at 2020-02-14 21:04:11.merged
by Axa Mei Liauw at 2020-02-14 21:04:12.closed
by Axa Mei Liauw at 2020-02-14 21:04:12.head_ref_deleted
by Axa Mei Liauw at 2020-02-14 21:04:15.head_ref_force_pushed
by None at 2020-02-14 20:31:00.head_ref_force_pushed
by None at 2020-02-14 20:48:55.head_ref_force_pushed
by None at 2020-02-14 21:11:38.closed
by Axa Mei Liauw at 2020-02-14 21:43:05.@axamei fixed up the rows. It will need to be rebased with the circle branch though to pass ci.
head_ref_force_pushed
by None at 2020-02-14 20:59:05.mentioned
by Axa Mei Liauw at 2020-02-14 21:10:14.subscribed
by Axa Mei Liauw at 2020-02-14 21:10:14.head_ref_force_pushed
by None at 2020-02-14 21:10:58.referenced
by Axa Mei Liauw at 2020-02-14 21:43:05.merged
by Axa Mei Liauw at 2020-02-14 21:43:05.closed
by Axa Mei Liauw at 2020-02-14 21:43:05.head_ref_deleted
by Axa Mei Liauw at 2020-02-14 21:43:11.referenced
by Axa Mei Liauw at 2020-02-14 21:45:45.merged
by Axa Mei Liauw at 2020-02-14 21:45:46.closed
by Axa Mei Liauw at 2020-02-14 21:45:46.head_ref_deleted
by Axa Mei Liauw at 2020-02-14 21:45:49.closed
by Eliot Jordan at 2020-02-13 22:03:19.referenced
by Eliot Jordan at 2020-02-13 22:03:19.merged
by Eliot Jordan at 2020-02-13 22:03:19.closed
by Eliot Jordan at 2020-02-13 22:03:19.head_ref_deleted
by Eliot Jordan at 2020-02-13 22:03:22.I was trying to resolve this by adjusting app/javascript/helpers/setup_ajax_select.js
, but I now suspect that the Vue components should be bound when listening for https://github.com/nathanvda/cocoon/blob/v1.2.12/app/assets/javascripts/cocoon.js#L96
Otherwise, the partial provided with app/views/records/edit_fields/_numismatic_citation_fields.html.erb
in https://github.com/pulibrary/figgy/blob/master/app/views/records/edit_fields/_numismatic_citation.html.erb#L8
does not actually trigger the mounting of the AjaxSelect
component.
assigned
by Christina Chortaria at 2020-02-14 15:46:26.labeled
by Christina Chortaria at 2020-02-14 15:51:15.labeled
by Christina Chortaria at 2020-02-14 15:51:34.labeled
by Christina Chortaria at 2020-02-14 15:51:40.@jrgriffiniii Yes they will have to upload monogram image files.
mentioned
by James R. Griffin III at 2020-02-14 16:37:10.subscribed
by James R. Griffin III at 2020-02-14 16:37:10.Implemented.
closed
by Eliot Jordan at 2020-02-14 17:18:03.closed
by James R. Griffin III at 2020-02-14 17:20:15.head_ref_force_pushed
by Eliot Jordan at 2020-02-13 22:24:00.review_requested
by James R. Griffin III at 2020-02-14 17:00:45.deployed
by Trey Pendragon at 2020-02-14 17:01:44.referenced
by James R. Griffin III at 2020-02-14 17:20:14.merged
by James R. Griffin III at 2020-02-14 17:20:14.closed
by James R. Griffin III at 2020-02-14 17:20:15.head_ref_deleted
by James R. Griffin III at 2020-02-14 17:20:19.I could only match one of the Selucid monogram images to an existing monogram images. Created a new MonogramImages directory on the Isilon. Rest is up to the numismatics lab.
closed
by Eliot Jordan at 2020-02-14 18:32:44.labeled
by James R. Griffin III at 2020-02-14 18:58:07.labeled
by James R. Griffin III at 2020-02-14 18:58:07.mentioned
by James R. Griffin III at 2020-02-14 19:26:13.subscribed
by James R. Griffin III at 2020-02-14 19:26:13.assigned
by Christina Chortaria at 2020-02-14 19:26:13.This is working for me locally, I've just been struggling with implementing feature tests (the Capybara/Selenium element selectors are not functioning as expected).
This isn't completely ready to be merged, however, I would need to please request a review in response to https://github.com/pulibrary/figgy/pull/3680/files#r379537180
head_ref_force_pushed
by James R. Griffin III at 2020-02-14 16:47:46.renamed
by James R. Griffin III at 2020-02-14 16:48:10.deployed
by Trey Pendragon at 2020-02-14 17:25:28.head_ref_force_pushed
by James R. Griffin III at 2020-02-14 19:03:34.head_ref_force_pushed
by James R. Griffin III at 2020-02-14 21:13:21.head_ref_force_pushed
by James R. Griffin III at 2020-02-14 16:59:40.review_dismissed
by James R. Griffin III at 2020-02-14 18:18:21.head_ref_force_pushed
by James R. Griffin III at 2020-02-14 18:18:21.head_ref_force_pushed
by James R. Griffin III at 2020-02-14 19:06:39.head_ref_force_pushed
by James R. Griffin III at 2020-02-14 21:13:56.referenced
by Christina Chortaria at 2020-02-14 21:06:57.merged
by Christina Chortaria at 2020-02-14 21:06:57.closed
by Christina Chortaria at 2020-02-14 21:06:57.head_ref_deleted
by Eliot Jordan at 2020-02-14 21:16:34.head_ref_force_pushed
by Christina Chortaria at 2020-02-14 20:43:12.head_ref_force_pushed
by Christina Chortaria at 2020-02-14 21:16:56.Coverage remained the same at 96.434% when pulling fa658404d5a9f275d8abcac145bfbd44e54a2425 on document-reserves-core into 7ffe8f1c3e13b9fee9603559d53fa0b63bc98b8c on master.
Maybe an ADR for this too? We do a cross-core join because the reserves core is updated at the same time as the query, and then instantly committed. Commits on the main core were too slow.
Coverage remained the same at 100.0% when pulling 58a6cec73819384a02db00128846f049108e98e0 on princetononlysync into b21f38f2bc2e89cd83058bbba155b38988c3577a on master.
deployed
by Trey Pendragon at 2020-02-14 21:39:29.closed
by Trey Pendragon at 2020-02-14 21:47:36.reopened
by Trey Pendragon at 2020-02-14 21:57:05.deployed
by Trey Pendragon at 2020-02-14 22:04:37.referenced
by Trey Pendragon at 2020-02-14 22:31:35.referenced
by Trey Pendragon at 2020-02-14 22:32:52.merged
by Trey Pendragon at 2020-02-14 22:32:52.closed
by Trey Pendragon at 2020-02-14 22:32:52.head_ref_deleted
by Trey Pendragon at 2020-02-14 22:32:56.@kevinreiss this is on https://library-staging.princeton.edu/exhibitions#
renamed
by Axa Mei Liauw at 2020-02-14 15:02:03.head_ref_force_pushed
by Axa Mei Liauw at 2020-02-14 18:22:10.renamed
by Axa Mei Liauw at 2020-02-14 18:22:59.mentioned
by Kevin Reiss at 2020-02-14 21:37:43.subscribed
by Kevin Reiss at 2020-02-14 21:37:43.referenced
by Kevin Reiss at 2020-02-14 21:47:22.merged
by Kevin Reiss at 2020-02-14 21:47:22.closed
by Kevin Reiss at 2020-02-14 21:47:22.head_ref_deleted
by Kevin Reiss at 2020-02-14 21:47:26.referenced
by None at 2020-02-14 20:24:38.referenced
by None at 2020-02-14 20:42:16.head_ref_force_pushed
by Nikitas Tampakis at 2020-02-14 15:22:24.head_ref_force_pushed
by None at 2020-02-14 20:42:16.labeled
by Amanda Ferrara at 2020-02-14 19:59:57.labeled
by Amanda Ferrara at 2020-02-14 19:59:57.labeled
by Amanda Ferrara at 2020-02-14 19:59:57.head_ref_force_pushed
by None at 2020-02-14 16:25:27.head_ref_force_pushed
by None at 2020-02-14 16:28:11.referenced
by None at 2020-02-14 16:29:37.merged
by None at 2020-02-14 16:29:37.closed
by None at 2020-02-14 16:29:37.head_ref_deleted
by None at 2020-02-14 16:29:42.


I am a postdoctoral researcher in the Robotics Research Group at KU Leuven since January 2019. My research interests lie in the areas of artificial intelligence, automated planning, robotics, and robot learning. I completed my Ph.D. in AI Planning and Robotics in the Institute of Electronics and Informatics Engineering of Aveiro (IEETA) at the University of Aveiro, Portugal. My doctoral dissertation contributes to the development of novel algorithms for knowledge representation and robot learning and task planning. My current research focuses on filling the gap between AI and robotics by the integration of AI planning into real robotic systems. My research has resulted in the development of some state-of-the-art techniques and open source tools in order for robot programming and planning.


{% extends "base.html" %} {% load commonmark %} {% load bootstrap3 %} {% block title %} Feedback | {{ block.super }} {% endblock %} {% block content %}
BornHack can always improve, but we need your feedback to know how. So write your thoughts on what was good and what wasn't at {{ camp.title }}, it's highly appreciated!


[[${#httpServletRequest.remoteUser}]]
Revoked Certificate
Revoked Certificate
Home
showDetails
downloadCerts
generateQR
×
qrcode
×
Certificate Details


We opened our doors 5 years ago in this great community. Over the years we've seen it grow, and our goal is to continue contibuting day in and day out.
It is important for us to be what we consider a pivotal and central area of this movement in Miami, and this is why we chose Wynwood.


--- layout: default robots: noindex ---
Santa Online is a non-official, non-profit fansite for Uno Santa, owned by Sybil.
All content is collected by Sybil and 点子 for Claus.
All pictures, videos and other media are copyrighted to their respective owners, no copyright infringement is ever intended. If you wish anything to be removed, please email us.


Our 2015 default theme is clean, blog-focused, and designed for clarity.
Twenty Fifteens simple, straightforward typography is readable on a
wide variety of screen sizes, and suitable for multiple languages. We
designed it using a mobile-first approach, meaning your content takes
center-stage, regardless of whether your visitors arrive by smartphone,
tablet, laptop, or desktop computer.
Our 2015 default theme is clean, blog-focused, and designed for clarity.
Twenty Fifteens simple, straightforward typography is readable on a
wide variety of screen sizes, and suitable for multiple languages. We
designed it using a mobile-first approach, meaning your content takes
center-stage, regardless of whether your visitors arrive by smartphone,
tablet, laptop, or desktop computer.