inserting spaces inbetween only capital letters that are directly adjacent to each other

Viewed 66

My goal is to add spaces in between letters of various abbreviations.

There are three conditions for abbreviations:

  1. abbreviations contain at least two or more letters.
  2. abbreviations are always capitalized.
  3. special character "/" is considered a capitalized letter

think of DNS, IP, TCP/IP, etc.

I would like to do text processing on them to turn into:

D N S

I P

T C P / I P

etc. Lets say I have this sentence

Because IP provides this basic routing function, the term “IP router,” is often used. Other, older terms for router are (IP gateway), [Internet gateway], and 'gateway'. TCP/IP 12345.

Running this command kinda solves my problem: sed -e "s/[a-z \, \. \' \“ \” \( \) 0-9]*/& /g" -e "s/ */ /g" test.txt It doesn't get it quite perfectly.

I get this:

Because I P provides this basic routing function, the term “ I P router,” is often used. Other, older terms for router are ( I P gateway), [ Internet gateway ], and 'gateway'. T C P / I P 12345.

There is still a space between " and I P .

There is a space between ( and I P .

There is also a space between [ and Internet.

escaping [ and ] with $ sed -e "s/[a-z \, \. \' \“ \” \( \) \[ \] 0-9]*/& /g" -e "s/ */ /g" test.txt doesn't work as shown below.

Because IP provides this basic routing function, the term “IP router,” is often used. Other, older terms for router are (IP gateway), [Internet gateway], and 'gateway'. TCP/IP 12345.

2 Answers

With GNU sed and a conditional jump:

echo 'think of DNS, IP, TCP/IP, etc.' | sed -E ':x; s/([A-Z/])([A-Z/])/\1 \2/; tx'

Output:

think of D N S, I P, T C P / I P, etc.

The regular expression

/([A-Z])([A-Z])/

Will match instances of two capital letters next to each other. You'd then want to use capturing groups in the replacement to get the same letters with a space between them.

/\1 \2/

This will only catch the first two capital letters in a row, so the output after the first iteration would look like:

Think of D NS, I P, T CP/I P, etc.

Therefore you need to repeat the substitution until the regex doesn't match. In Python this would be:

the_string = 'Think of DNS, IP, TCP/IP, etc.'

while re.search(r'([A-Z])([A-Z])', the_string):
    the_string = re.sub(r'([A-Z])([A-Z])', r'\1 \2', the_string)

the_string now ends up as:

Think of D NS, I P, T CP/I P, etc.
Related