How to use a regex variable in a regular expression? - python

I am using the following pattern to clean a piece of text (replacing the matches with null):
{\s{\s\"[A-Za-z0-9.,\-:]*(?<!\bbecause\b)(?<!\bsince\b)\"\s}\s\"[A-Za-z0-9.,\-:]*\"\s}
I have a list of relators like "because" and "since" that could change every time. So I created a separate string which is a regex itself like:
lookahead_string = (?<!\bbecause\b)(?<!\bsince\b)
And put it in my original regex pattern and changed it like the following:
{\s{\s\"[A-Za-z0-9.,\-:]*'+lookahead_string+r'\"\s}\s\"[A-Za-z0-9.,\-:]*\"\s}
But the new pattern does not match the parts of the input text that could be matched using the original regex pattern. The code I am using is:
lookahead_string = ''
relators = ["because", "since"]
for rel in relators:
lookahead_string += '(?<!\b'+rel+'\b)'
text = re.sub(r'{\s{\s\"[A-Za-z0-9.,\-:]*'+lookahead_string+r'\"\s}\s\"[A-Za-z0-9.,\-:]*\"\s}', "", text)
text = ' '.join(text.split())
What should I do to make it work?! I have already tried using re.escape and format string but none of them works in my case.
Edit: I removed the input output text because I thought it is a little confusing. However, I thank #DYZ for the good suggestion.

A suggestion: Instead of messing up with the complex string syntax, convert the string to a Python list.
import ast
l = ast.literal_eval("[" + s.replace("}", "],").replace("{", "[") + "]")
#[[[[['I'], 'PRP'], 'NP'], [[[[['did'], 'VBD'], [['not'], 'RB'], 'VP'],
# ..., 'S'], '']
Now you can apply simple list functions to your data and, when done, transform the list to a bracketed string.

Related

replace before and after a string using re in python

i have string like this 'approved:rakeshc#IAD.GOOGLE.COM'
i would like extract text after ':' and before '#'
in this case the test to be extracted is rakeshc
it can be done using split method - 'approved:rakeshc#IAD.GOOGLE.COM'.split(':')[1].split('#')[0]
but i would want this be done using regular expression.
this is what i have tried so far.
import re
iptext = 'approved:rakeshc#IAD.GOOGLE.COM'
re.sub('^(.*approved:)',"", iptext) --> give everything after ':'
re.sub('(#IAD.GOOGLE.COM)$',"", iptext) --> give everything before'#'
would want to have the result in single expression. expression would be used to replace a string with only the middle string
Here is a regex one-liner:
inp = "approved:rakeshc#IAD.GOOGLE.COM"
output = re.sub(r'^.*:|#.*$', '', inp)
print(output) # rakeshc
The above approach is to strip all text from the start up, and including, the :, as well as to strip all text from # until the end. This leaves behind the email ID.
Use a capture group to copy the part between the matches to the result.
result = re.sub(r'.*approved:(.*)#IAD\.GOOGLE\.COM$', r'\1', iptext)
Hope this works for you:
import re
input_text = "approved:rakeshc#IAD.GOOGLE.COM"
out = re.search(':(.+?)#', input_text)
if out:
found = out.group(1)
print(found)
You can use this one-liner:
re.sub(r'^.*:(\w+)#.*$', r'\1', iptext)
Output:
rakeshc

Replace Items with regex (kind of)

I am handed a bunch of data and trying to get rid of certain characters. The data contains multiple instances of "^{number}" → "^0", "^1", "^2", etc.
I am trying to set all of these instances to an empty string, "", is there a better way to do this than
string.replace("^0", "").replace("^1", "").replace("^2", "")
I understand you can use a dictionary, but it seems a little overkill considering each item will be replaced with "".
I understand that the digits are always at the end of the string, have a look at the solutions below.
with regex:
import re
text = 'xyz125'
s = re.sub("\d+$",'', text)
print(s)
it should print:
'xyz'
without regex, keep in mind that this solution removes all digits and not only the ones at the end of a string:
text = 'xyz125'
result = ''.join(i for i in text if not i.isdigit())
print(result)
it should print:
'xyz'

Updating a string using regular expressions in Python

I'm pretty sure that my question is very straightforward but I cannot find the answer to it. Let's say we have an input string like:
input = "This is an example"
Now, I want to simply replace every word --generally speaking, every substring using a regular expression, "word" here is just an example-- in the input with another string which includes the original string too. For instance, I want to add an # to the left and right of every word in input. And, the output would be:
output = "#This# #is# #an# #example#"
What is the solution? I know how to use re.sub or replace, but I do not know how I can use them in a way that I can update the original matched strings and not completely replace them with something else.
You can use capture groups for that.
import re
input = "This is an example"
output = re.sub("(\w+)", "#\\1#", input)
A capture group is something that you can later reference, for example in the substitution string. In this case, I'm matching a word, putting it into a capture group and then replacing it with the same word, but with # added as a prefix and a suffix.
You can read about regexps in python more in the docs.
Here is an option using re.sub with lookarounds:
input = "This is an example"
output = re.sub(r'(?<!\w)(?=\w)|(?<=\w)(?!\w)', '#', input)
print(output)
#This# #is# #an# #example#
This is without re library
a = "This is an example"
l=[]
for i in a.split(" "):
l.append('#'+i+'#')
print(" ".join(l))
You can match only word boundaries with \b:
import re
input = "This is an example"
output = re.sub(r'\b', '#', input)
print(output)
#This# #is# #an# #example#

Search for string in file while ignoring id and replacing only a substring

I’ve got a master .xml file generated by an external application and want to create several new .xmls by adapting and deleting some rows with python. The search strings and replace strings for these adaptions are stored within an array, e.g.:
replaceArray = [
[u'ref_layerid_mapping="x4049" lyvis="off" toc_visible="off"',
u'ref_layerid_mapping="x4049" lyvis="on" toc_visible="on"'],
[u'<TOOL_BUFFER RowID="106874" id_tool_base="3651" use="false"/>',
u'<TOOL_BUFFER RowID="106874" id_tool_base="3651" use="true"/>'],
[u'<TOOL_SELECT_LINE RowID="106871" id_tool_base="3658" use="false"/>',
u'<TOOL_SELECT_LINE RowID="106871" id_tool_base="3658" use="true"/>']]
So I'd like to iterate through my file and replace all occurences of 'ref_layerid_mapping="x4049" lyvis="off" toc_visible="off"' with 'ref_layerid_mapping="x4049" lyvis="on" toc_visible="on"' and so on.
Unfortunately the ID values of "RowID", “id_tool_base” and “ref_layerid_mapping” might change occassionally. So what I need is to search for matches of the whole string in the master file regardless which id value is inbetween the quotation mark and only to replace the substring that is different in both strings of the replaceArray (e.g. use=”true” instead of use=”false”). I’m not very familiar with regular expressions, but I think I need something like that for my search?
re.sub(r'<TOOL_SELECT_LINE RowID="\d+" id_tool_base="\d+" use="false"/>', "", sentence)
I'm happy about any hint that points me in the right direction! If you need any further information or if something is not clear in my question, please let me know.
One way to do this is to have a function for replacing text. The function would get the match object from re.sub and insert id captured from the string being replaced.
import re
s = 'ref_layerid_mapping="x4049" lyvis="off" toc_visible="off"'
pat = re.compile(r'ref_layerid_mapping=(.+) lyvis="off" toc_visible="off"')
def replacer(m):
return "ref_layerid_mapping=" + m.group(1) + 'lyvis="on" toc_visible="on"';
re.sub(pat, replacer, s)
Output:
'ref_layerid_mapping="x4049"lyvis="on" toc_visible="on"'
Another way is to use back-references in replacement pattern. (see http://www.regular-expressions.info/replacebackref.html)
For example:
import re
s = "Ab ab"
re.sub(r"(\w)b (\w)b", r"\1d \2d", s)
Output:
'Ad ad'

Python : How to ignore a delimited part of a sentence?

I have the following line :
CommonSettingsMandatory = #<Import Project="[\\.]*Shared(\\vc10\\|\\)CommonSettings\.targets," />#,true
and i want the following output:
['commonsettingsmandatory', '<Import Project="[\\\\.]*Shared(\\\\vc10\\\\|\\\\)CommonSettings\\.targets," />', 'true'
If i do a simple regex with the comma, it will split the value if there's a value in it, like i wrote a comma after targets, it will split here.
So i want to ignore the text between the ## to make sure there's no splitting there.
I really don't know how to do!
http://docs.python.org/library/re.html#re.split
import re
string = 'CommonSettingsMandatory = #toto,tata#, true'
splitlist = re.split('\s?=\s?#(.*?)#,\s?', string)
Then splitlist contains ['CommonSettingsMandatory', 'toto,tata', 'true'].
While you might be able to use split with a lookbehind, I would use the groups captured by this expression.
(\S+)\s*=\s*##([^#]+)##,\s*(.*)
m = re.Search(expression, myString). use m.group(1) for the first string, m.group(2) for the second, etc.
If I understand you correctly, you're trying to split the string using spaces as delimiters, but you want to also remove any text between pound signs?
If that's correct, why not simply remove the pound sign-delimited text before splitting the string?
import re
myString = re.sub(r'#.*?#', '', myString)
myArray = myString.split(' ')
EDIT: (based on revised question)
import re
myArray = re.findall(r'^(.*?) = #(.*?)#,(.*?)$', myString)
That will actually return an array of tuples including your matches, in the form of:
[
(
'commonsettingsmandatory',
'<Import Project="[\\\\.]*Shared(\\\\vc10\\\\|\\\\)CommonSettings\\.targets," />',
'true'
)
]
(spacing added to illustrate the format better)

Categories

Resources