some_text = "  Postman Pat has a cat named Jess.  "

"""
Explanation: String processing
Let us start by having a look at some of the functionality that is built into Python strings.
The Python string object
The Python string object has many useful features built into it. Let us look at some of these.
End of explanation
"""


stripped_text = some_text.strip()
stripped_text

"""
Explanation: Note that the text starts and ends with some whitespace characters. One often wants to get rid of these.
End of explanation
"""


some_text.lstrip()

some_text.rstrip()

"""
Explanation: It is possible to do this only for the left/right hand side of the string.
End of explanation
"""


stripped_text.startswith("postman")

"""
Explanation: Another common scenarios is to check whether or not a string starts with a particular word.
End of explanation
"""


stripped_text.lower()

stripped_text.lower().startswith("postman")

"""
Explanation: Note that the above returns False as the words have different capitalisation. One can work around this by forcing the input text to be lower case.
End of explanation
"""


"/my/great/picture.png".endswith(".png")

"""
Explanation: There is also an endswith() method that can be useful for checking file extensions.
End of explanation
"""


some_text.find("cat")

"""
Explanation: Let us search for particular words within our string.
End of explanation
"""


some_text[20:23]

"""
Explanation: The find argument returns the index of the first letter of the search term.
End of explanation
"""


some_text.find("dog")

"""
Explanation: If the search term is not found the find() method returns -1.
End of explanation
"""


some_text.find("at")

"""
Explanation: If we search for something that exists more than once we get the index of the first instance.
End of explanation
"""


some_text.find("at", 12)

some_text.find("at", 22)

"""
Explanation: We can find the next instance by specifying the index to start the search from.
End of explanation
"""


"One cat, two cats, three cats.".replace("cat", "dog")

"""
Explanation: String objects also have functionality for enabling substitutions.
End of explanation
"""


"One cat, two cats, three cats.".replace("cat", "dog", 2)

"""
Explanation: It is possible to specify the number of substituitons that one wishes to make.
End of explanation
"""


some_text.split(" ")

"""
Explanation: One of the most useful features of string objects is the ability to split them based on a separator.
End of explanation
"""


some_text.strip().split(" ")

"""
Explanation: Note the extra items at the begining and end of the line arising from the extra white spaces. One can get around this by using the strip() function.
End of explanation
"""


"1,2,3,4".split(",")

"""
Explanation: This function is particularly useful when dealing with csv files.
End of explanation
"""


[s.strip() for s in "1, 2,3,    4".split(",")]

"""
Explanation: However, depending on your CSV file it may be safer to do something along the lines of the below.
Does everyone know what list comprehension is?
End of explanation
"""


[int(s.strip()) for s in "1, 2,3,    4".split(",")]

"""
Explanation: Futhermore, if you know that you are wanting to deal with integers you may even want to include the string to integer conversion as well.
End of explanation
"""


import re
some_text = "  Postman Pat has a cat named Jess.  "

"""
Explanation: There are many variaitons on the string operators described above. It is useful to familiarise yourself with the
Python documentation on strings.
Regular expressions
Regular expressions can be defined as a series of characters that define a search pattern.
Regular expressions can be very powerful. However, they can be difficult to build up. Often it is a process of trial and error. This means that once they have been created, and the trial and error process has been forgotten, it can be extremely difficult to understand what the regular expression does and why it is constructed the way it is.
Use regular expressions only as a last resort!
To use regular expressionsions in Python we need to import the re module.
End of explanation
"""


re.search(r"cat", some_text)

"""
Explanation: Let us search for the word "cat".
End of explanation
"""


match = re.search(r"cat", some_text)
if match:
    print(some_text[match.start():match.end()])

"""
Explanation: There are two things to note here:

We use a raw string to represent our regular expression
The regular expression search() method returns a match object (or None if no match is found)

The index of the first and last matched characters can be accessed as using the match object's start() and end() methods.
End of explanation
"""


match = re.search(r"\wat", some_text)
if match:
    print(match.string[match.start():match.end()])

"""
Explanation: Now suppose that we wanted the first letter to be any alphanumberic character. We can achieve this using the regular expression "word" meta character \w.
End of explanation
"""


matches = re.findall(r"\wat", some_text)
for m in matches:
    print(m)

"""
Explanation: It is also possible to find all matches. However, note that this returns strings as opposed to regular expression match objects.
End of explanation
"""


re.sub(r"\wat", "dog", some_text)

"""
Explanation: Similarly we can use regular expressions to perform substitutions.
End of explanation
"""


ncbi_header = ">gi|568336023|gb|CM000663.2| Homo sapiens chromosome 1, GRCh38 reference primary assembly."
match = re.search(r">gi\|[0-9]*\|\w*\|(\w*).([0-9])*\|.*", ncbi_header)

"""
Explanation: However, more commonly we want to extract particular pieces of information from a string. For example the accession and version from the NCBI header. (Format: ">gi|xx|dbsrc|accession.version|description".)
End of explanation
"""


match.groups()

"""
Explanation: Note how horrible and incomprehensible the regular expression is.
It took me a couple of attempts to get this one right as I forgot that | is a regular expression meta character that needs to be escaped using a backslash \.
However, we can now access the groups specified by the parenthesis.
End of explanation
"""


match.group(0)

match.group(1)

match.group(2)

"""
Explanation: Individual groups can also be accessed. Note that the first group includes everything matched by the regular expression.
End of explanation
"""


re.search(r"cat", "my cat has a hat")

print( re.match(r"cat", "my cat has a hat") )

re.match(r"my", "my cat has a hat")

"""
Explanation: Let us have a look at a common pitfall when using regular expressions in Python: the difference between the methods
search() and match().
End of explanation
"""


cat_regex = re.compile(r"cat")
cat_regex.search("my cat has a hat")

"""
Explanation: Basically match() only looks for a match at the beginning of the string to be searched. For more information see the
search() vs match() section in the Python documentation.
Finally if you are using the same regular expression many times you may find it advantageous to compile the regular expression. This may speed up your program.
End of explanation
"""


