0
$\begingroup$

I have a case like below:

  col1
  {hjjlhllllh
  :59:kjkjkjdd
  :50:/kjhjhjhsa:ddd
  :70:jnjjh


  kjkjytdvdjjh:fhghghghg
 :52:jkjkt
 :50K:kkcknkknn
 :72:nbnbds



  mvmmbmnnm{hghghgsl
 :65A:jjhjhjh
 :50B:iut6565vdjbj

:kjkjkj

I want it like below:

  col1                                                            col2

 {hjjlhllllh
  :59:kjkjkjdd
  :50:/kjhjhjhsa:ddd
  :70:jnjjh 
                                                               /kjhjhjhsa


 kjkjytdvdjjh:fhghghghg
 :52:jkjkt
 :50K:kkcknkknn
 :72:nbnbds 
                                                               kkcknkknn

 mvmmbmnnm{hghghgsl
:65A:jjhjhjh
:50B:iut6565vdjbj:kjkjkj                                     iut6565vdjbj

Now, I am able to get col 2 value for the 1st row by using a logic that whatever appears between '50' & ':', extract it. The Same logic does not stand correct for the other 2 rows where in I have to get that appears between '50K' or '50B' & ':'. I want to extract irrespective whatever be the prefix be for '50' without hardcoding. Can anyone help me in this?

$\endgroup$

1 Answer 1

1
$\begingroup$

This is a problem of identifying a good regular expression to parse the strings into their component parts. I made an assumption that this data is sitting in a DataFrame and you are trying to add a new column with the extracted string.

Code

import pandas as pd
import re

def extract_second_group(full_string):
    pattern = '^\S*:50.*:\W*(\w*):\S*$'

    match = re.search(pattern, full_string)
    if match is not None:
        return match.groups(0)[0]
    else:
        return None


df = pd.DataFrame(columns=['col1'])

df['col1'] = [
            '{kjkjkjdd:50:/kjhjhjhsa:ddd', 
              'kjkjytdvdjjh:50K:kkcknkknn:nbnbds', 
              'mvmmbmnnm{:50B:iut6565vdjbj:kjkjkj',
              'not a matching string'
]

df['col2'] = df['col1'].apply(lambda col1:extract_second_group(col1))
df

Explanation

The regex pattern is ^\S*:50.*:\W*(\w*):\S*$. Let's break it down to see what it is doing.

^ : Start of string
\S : Matches any character which is not a whitespace character
:50 : Match this exact set of characters (in that sequence)
. : matches any character except a newline
\W
: Matches any character which is not a word character (matches the (/) character, if any) (\w*): This is the most important part of the expression. The \w* matches Unicode word characters, while the parentheses tell us to create a group. We are interested in capturing this group
: : Another colon separates the group from the rest
\S* : Another non-whitespace sequence of characters
$ : End of string

The regex is enclosed in a function so that we can check when a regex search doesn't return a match. Call the apply() function to run each row through the function and return the matched group.

Edit Jul 24 2019

This edit is to reflect the change in the data from OP.

The problem remains a question about regular expressions. Here's the code for the updated dataset

Updated Code

import pandas as pd
import re

# https://docs.python.org/3.6/library/re.html
def extract_second_group(full_string):
    pattern = '\W*:50\w{0,1}:(/*[\w]*):\S*$'

    match = re.search(pattern, full_string)
    if match is not None:
        return match.groups(0)[0]
    else:
        return None



df = pd.DataFrame(columns=['col1'])

df['col1'] = [
            '{hjjlhllllh:59:kjkjkjdd:50:/kjhjhjhsa:ddd:70:jnjjh', 
              'kjkjytdvdjjh:fhghghghg:52:jkjkt:50K:kkcknkknn:72:nbnbds', 
              'mvmmbmnnm{hghghgsl:65A:jjhjhjh:50B:iut6565vdjbj:kjkjkj',
              'not a matching string'
]


df['col2'] = df['col1'].apply(lambda col1:extract_second_group(col1))
df

Output

$$\begin{array}{c|c|} & col1 & col2\\ \hline 0& \{hjjlhllllh:59:kjkjkjdd:50:/kjhjhjhsa:ddd:70:j... & /kjhjhjhsa\\ \hline 1& kjkjytdvdjjh:fhghghghg:52:jkjkt:50K:kkcknkknn:... & kkcknkknn\\ \hline 2& mvmmbmnnm\{hghghgsl:65A:jjhjhjh:50B:iut6565vdjb... & iut6565vdjbj\\ \hline 3& not a matching string & None\\ \end{array}$$

Updated Regex
The updated pattern is \W*:50\w{0,1}:(/*[\w]*):\S*$.
I updated it as follows

  1. \W* Start with some non-word characters
  2. :50\w{0,1} Followed by :50 and 0 or 1 Unicode word characters
  3. : Followed by a colon
  4. (/[\w]) Followed by the group we want. I included one or more / and any number of Unicode word characters.
  5. : Followed by a colon
  6. \S*$ Followed by any number of non-space characters to end of string



If there are other patterns you need to match, you can use the resources from https://docs.python.org/3.6/library/re.html to locate the different options available in regex patterns.

$\endgroup$
2
  • $\begingroup$ HI, I am getting the result as none. My actual data is little different from this one. My actual data is as updated. $\endgroup$
    – sayan sen
    Jul 24, 2019 at 12:11
  • $\begingroup$ I think the issue is that for each row, for every filed, the data is in the new line.so may be the expression needs to chnge $\endgroup$
    – sayan sen
    Jul 24, 2019 at 12:53

Not the answer you're looking for? Browse other questions tagged or ask your own question.