AWESOME :)
Another QUESTION:
What if I have multiple Sentences like:
[PROGRAMMING]-Old System-TRT Operates-192.168.6.0-qwert8-plain (AMB)
[PATCHING]-Old System-TRT Operates-192.168.6.0-qwert8-plain (CCB)
Notice that the last word that I need to take out varies from sentence to sentence. How can i make sure that I always take out the last part of the sentence. In this case; (AMB) and (CCB)
I also need to do the same with the words at the beginning:
[PROGRAMMING]
[PATCHING]
Thanks :)
You can use this for the part within []:
=MID(A2,2,FIND("]",A2)-2)
And this for the part within ():
=MID(A2,FIND("(",A2)+1,3)
googlespreadsheet sample
MID takes 3 parameters:
A text,
A starting position,
The length of the extracted text.
FIND takes 2-3 parameters and returns a position number:
Something it will look for,
The text in which it will look for the something,
The position from where it'll start looking. If not mentioned, looks from the beginning.
=MID(A2,2,FIND("]",A2)-2) with your first example becomes the following after replacing the innermost evaluation:
=MID(A2,2,FIND("]","[PROGRAMMING]-Old System-TRT Operates-192.168.6.0-qwert8-plain (AMB)")-2)
FIND("]","[PROGRAMMING]-Old System-TRT Operates-192.168.6.0-qwert8-plain (AMB)")
] appears at the 13th position, so this FIND() returns 13. The MID becomes:
=MID(A2,2,13-2) => =MID(A2,2,11)
And if you count the characters in PROGRAMMING, there are 11. I removed 2, because 1 is for the beginning [ to be removed, the second is for the ] to be removed.
Now, it becomes:
=MID("[PROGRAMMING]-Old System-TRT Operates-192.168.6.0-qwert8-plain (AMB)",2,11)
Which means start (including) at character 2 and take 11 characters, which gives the text you are looking for.
The one for () is just as simple if you got the above.
You can use the MID() function if the data always follows the same pattern.
=MID(A1, FIND("(",A1, 1) + 1, LEN(A1)-FIND("(",A1, 1)-1)
Assuming the string is in A1. The first parameter is the string. The second is the start of the substring to extract. You want to start one character past the first parenthesis. The last parameter is the length of the substring to extract. You want to take the whole string minus all the characters before the parenthesis and also ignore the last parenthesis (thus the -1).
Related
Given a tweet dataset from this link which has a content column as follows:
I hope to add one new column to identify whether or not the tweet mentioned Trump. The regex patern (^|[^A-Za-z0-9])Trump([^A-Za-z0-9]|$) seems work out, but I don't understand well. I've tested with the code below:
Test1 gives the output since it's matched:
txt1 = "anti-Trump protesters"
re.search("(^|[^A-Za-z0-9])Trump([^A-Za-z0-9]|$)", txt1)
Out:
<_sre.SRE_Match object; span=(4, 11), match='-Trump '>
Test2 return None since it's not matched as expected:
txt2 = 'I got Trumped'
re.search("(^|[^A-Za-z0-9])Trump([^A-Za-z0-9]|$)", txt2)
Someone could help to explain a little bit about this pattern. Many thanks at advance.
The (^|[^A-Za-z0-9]) portion has |, which means “or”. The left side, the ^, is the start of the string. The right side, [^A-Za-z0-9], matches any character that is not a letter or a number. In short, it matches when “Trump” is at the start of the string, or is preceded by a non-alphanumeric character.
The ([^A-Za-z0-9]|$) follows a similar pattern, where the left side matches any character that is not a letter or a number. The right side, the $ matches the end of the string. Likewise, it matches when “Trump” is at the end of the string or is followed by a non-alphanumeric character.
So, bottom line, it matches “Trump“ that is either at the start of the string or is preceded by any character that is not alphanumeric, as well as matches if it is also and the end of the string or is followed by a non-alphanumeric character.
heres the question:
Remove First and Last Character
It's pretty straightforward. Your goal is to create a function that removes the first and last characters of a string. You're given one parameter, the original string. You don't have to worry with strings with less than two characters.
i have no idea how to do it because of the fact that it wants me to remove first and last letter and not the first and last word
Slicing is the best way to go about that.
test_string = 'This is a test!'
print (test_string [1:-1])
From your response that removing the first and last word would be done by list1.pop() and list1.pop(0) I am assuming that you are given a list of strings and are required to remove the first and last character of each string in the list.
If my assumption is correct you can do a combination of slicing and list comprehension.
list_of_str = ["words", "words", "words", "words"]
list_of_shortened_str = [word[1:-1] for word in list_of_str]
# list_of_shortened_str = ["ord", "ord", "ord", "ord"]
I've been trying for about two hours now to write a regular expression which matches a single character that's not preceded or followed by the same character.
This is what I've got: (\d)(?<!\1)\1(?!\1); but it doesn't seem to work! (testing at https://regex101.com/r/whnj5M/6)
For example:
In 1111223 I would expect to match the 3 at the end, since it's not preceded or followed by another 3.
In 1151223 I would expect to match the 5 in the middle, and the 3 at the end for the same reasons as above.
The end goal for this is to be able to find pairs (and only pairs) of characters in strings (e.g. to find 11 in 112223 or 44 in 123544) and I was going to try and match single isolated characters, and then add a {2} to it to find pairs, but I can't even seem to get isolated characters to match!
Any help would be much appreciated, I thought I knew RegEx pretty well!
P.S. I'm testing in JS on regex101.com because it wouldn't let me use variable length lookbacks in Python on there, and I'm using the regex library to allow for this in my actual implementation.
Your regex is close, but by using simply (\d) you are consuming characters, which prevents the other match from occurring. Instead, you can use a positive lookahead to set the capture group and then test for any occurrences of the captured digit not being surrounded by copies of itself:
(?=.*?(.))(?<!\1)\1(?!\1)
By using a lookahead you avoid consuming any characters and so the regex can match anywhere in the string.
Note that in 1151223 this returns 5, 1 and 3 because the third 1 is not adjacent to any other 1s.
Demo on regex101 (requires JS that supports variable width lookbehinds)
The pattern you tried does not match because this part (\d)(?<!\1) can not match.
It reads as:
Capture a digit in group 1. Then, on the position after that captured
digit, assert what is captured should not be on the left.
You could make the pattern work by adding for example a dot after the backreference (?<!\1.) to assert that the value before what you have just matched is not the same as group 1
Pattern
(\d)(?<!\1.)\1(?!\1)
Regex demo | Python demo
Note that you have selected ECMAscript on regex101.
Python re does not support variable width lookbehind.
To make this work in Python, you need the PyPi regex module.
Example code
import regex
pattern = r"(\d)(?<!\1.)\1(?!\1)"
test_str = ("1111223\n"
"1151223\n\n"
"112223\n"
"123544")
matches = regex.finditer(pattern, test_str)
for matchNum, match in enumerate(matches, start=1):
print(match.group())
Output
22
11
22
11
44
#Theforthbird has provided a good explanation for why your regular explanation does not match the characters of interest.
Each character matched by the following regular expression is neither preceded nor followed by the same character (including characters at the beginning and end of the string).
r'^.$|^(.)(?!\1)|(?<=(.))(?!\2)(.)(?!\3)'
Demo
Python's re regex engine performs the following operations.
^.$ match the first char if it is the only char in the line
| or
^ match beginning of line
(.) match a char in capture group 1...
(?!\1) ...that is not followed by the same character
| or
(?<=(.)) save the previous char in capture group 2...
(?!\2) ...that is not equal to the next char
(.) match a character and save to capture group 3...
(?!\3) ...that is not equal to the following char
Suppose the string were "cat".
The internal string pointer is initially at the beginning of the line.
"c" is not at the end of the line so the first part of the alternation fails and the second part is considered.
"c" is matched and saved to capture group 1.
The negative lookahead asserting that "c" is not followed by the content of capture group 1 succeeds, so "c" is matched and the internal string pointer is advanced to a position between "c" and "a".
"a" fails the first two parts of the assertion so the third part is considered.
The positive lookbehind (?<=(.)) saves the preceding character ("c") in capture group 2.
The negative lookahead (?!\2), which asserts that the next character ("a") is not equal to the content of capture group 2, succeeds. The string pointer remains just before "a".
The next character ("a") is matched and saved in capture group 3.
The negative lookahead (?!\3), which asserts that the following character ("t") does not equal the content of capture group 3, succeeds, so "a" is matched and the string pointer advances to just before "t".
The same steps are performed when evaluating "t" as were performed when evaluating "a". Here the last token ((?!\3)) succeeds, however, because no characters follow "t".
Extracting a specific word and a number of tokens on each side of it from each string in a column in SAS EG ?
For example,
row1: the sun is nice
row2: the sun looks great
row3: the sun left me
Is there a code that would produce the following result column (2 words where sun is the first):
SUN IS
SUN LOOKS
SUN LEFT
and possibly a second column with COUNT in case of duplicate matches.
So if there was 20 SUN LOOKS then it they would be grouped and have a count of 20.
Thanks
I think you can use functions findw() and scan() to do want you want. Both of those functions operate on the concept of word boundaries. findw() returns the position of the word in the string. Once you know the position, you can use scan() in a loop to get the next word or words following it.
Here is a simple example to show you the concept. It is by no means a finished or polished solution, but intended you point you in the right direction. The input data set (text) contains the sentences you provided in your question with slight modifications. The data step finds the word "sun" in the sentence and creates a variable named fragment that contains 3 words ("sun" + the next 2 words).
data text2;
set text;
length fragment $15;
word = 'sun'; * search term;
fragment_len = 3; * number of words in target output;
word_pos = findw(sentence, word, ' ', 'e');
if word_pos then do;
do i = 0 to fragmen_len-1;
fragment = catx(' ', fragment, scan(sentence, word_pos+i));
end;
end;
run;
Here is a partial print of the output data set.
You can use a combination of the INDEX, SUBSTR and SCAN functions to achieve this functionality.
INDEX - takes two arguments and returns the position at which a given substring appears in a string. You might use:
INDEX(str,'sun')
SUBSTR - simply returns a substring of the provided string, taking a second numeric argument referring to the starting position of the substring. Combine this with your INDEX function:
SUBSTR(str,INDEX(str,'sun'))
This returns the substring of str from the point where the word 'sun' first appears.
SCAN - returns the 'words' from a string, taking the string as the first argument, followed by a number referring to the 'word'. There is also a third argument that specifies the delimiter, but this defaults to space, so you wouldn't need it in your example.
To pick out the word after 'sun' you might do this:
SCAN(SUBSTR(str,INDEX(str,'sun')),2)
Now all that's left to do is build a new string containing the words of interest. That can be achieved with concatenation operators. To see how to concatenate two strings, run this illustrative example:
data _NULL_;
a = 'Hello';
b = 'World';
c = a||' - '||b;
put c;
run;
The log should contain this line:
Hello - World
As a result of displaying the value of the c variable using the put statement. There are a number of functions that can be used to concatenate strings, look in the documentation at CAT,CATX,CATS for some examples.
Hopefully there is enough here to help you.
I would like to implement a function with R that removes repeated characters in a string. For instance, say my function is named removeRS, so it is supposed to work this way:
removeRS('Buenaaaaaaaaa Suerrrrte')
Buena Suerte
removeRS('Hoy estoy tristeeeeeee')
Hoy estoy triste
My function is going to be used with strings written in spanish, so it is not that common (or at least correct) to find words that have more than three successive vowels. No bother about the possible sentiment behind them. Nonetheless, there are words that can have two successive consonants (especially ll and rr), but we could skip this from our function.
So, to sum up, this function should replace the letters that appear at least three times in a row with just that letter. In one of the examples above, aaaaaaaaa is replaced with a.
Could you give me any hints to carry out this task with R?
I did not think very carefully on this, but this is my quick solution using references in regular expressions:
gsub('([[:alpha:]])\\1+', '\\1', 'Buenaaaaaaaaa Suerrrrte')
# [1] "Buena Suerte"
() captures a letter first, \\1 refers to that letter, + means to match it once or more; put all these pieces together, we can match a letter two or more times.
To include other characters besides alphanumerics, replace [[:alpha:]] with a regex matching whatever you wish to include.
I think you should pay attention to the ambiguities in your problem description. This is a first stab, but it clearly does not work with "Good Luck" in the manner you desire:
removeRS <- function(str) paste(rle(strsplit(str, "")[[1]])$values, collapse="")
removeRS('Buenaaaaaaaaa Suerrrrte')
#[1] "Buena Suerte"
Since you want to replace letters that appear AT LEAST 3 times, here is my solution:
gsub("([[:alpha:]])\\1{2,}", "\\1", "Buennaaaa Suerrrtee")
#[1] "Buenna Suertee"
As you can see the 4 "a" have been reduced to only 1 a, the 3 r have been reduced to 1 r but the 2 n and the 2 e have not been changed.
As suggested above you can replace the [[:alpha:]] by any combination of [a-zA-KM-Z] or similar, and even use the "or" operator | inside the squre brackets [y|Q] if you want your code to affect only repetitions of y and Q.
gsub("([a|e])\\1{2,}", "\\1", "Buennaaaa Suerrrtee")
# [1] "Buenna Suerrrtee"
# triple r are not affected and there are no triple e.