10

I have a strings:

AddData
TestSomething
TellMeWhoYouAre

and so on. I want to add space before uppercase letters. How can I do it?

2
  • 7
    What do you want to do when there are consecutive upper case letters? example IClimbALadder – glenn jackman Feb 1 '17 at 15:26
  • 1
    Actually I have a strings like ReadFileFromCDDrive and @Kusalananda 's solution works great. – HeroFromEarth Feb 2 '17 at 6:06
17

Using sed, and assuming you don't want a space in front of the word:

$ sed 's/\([^[:blank:]]\)\([[:upper:]]\)/\1 \2/g' file.in
Add Data
Test Something
Tell Me Who You Are

The substitution will look for an upper-case letter immediately following a another non-whitespace character, and insert a space in-between the two.

For strings with more than one consecutive upper-case character, like WeAreATeam, this produces We Are ATeam. To sort this, run the substitution a second time:

$ sed -e 's/\([^[:blank:]]\)\([[:upper:]]\)/\1 \2/g' \
      -e 's/\([^[:blank:]]\)\([[:upper:]]\)/\1 \2/g' file.in
9
  • 1
    This answer won't add a space before an uppercase letter if it's preceded by an uppercase letter. Why write it that way, when the OP didn't put any such restriction on it? – LarsH Feb 1 '17 at 21:32
  • @LarsH Fixed it. – Kusalananda Feb 1 '17 at 21:54
  • No you didn't. You can't have overlapping matches to a regex, even with a g flag. Try echo ThisIsATest | sed 's/\(.\)\([[:upper:]]\)/\1 \2/g' (your command) to see why it doesn't work. – Wildcard Feb 1 '17 at 23:27
  • @Wildcard Wonky, but works. Do you have a better suggestion using BREs? – Kusalananda Feb 1 '17 at 23:52
  • It doesn't actually say no space at the start, so s/[A-Z]/ \0/g is entirely satisfactory... `s/[A-Z]/ \0/g;s/^ //' if you really care. – Michael Homer Feb 2 '17 at 0:17
12

Perl, using lookbehind and lookahead zero-width regular expressions:

$ perl -pe 's/(?<=\w)(?=[A-Z])/ /g'  file.in 

Tell Me Who You Are                    ## TellMeWhoYouAre
I Am A Regular Expression User         ## IAmARegulaExpressionUser

This version is also separating consecutive uppercase letters.

3
  • 1
    This turns ReadFileFromUSBDrive into Read File From U S B Drive whereas the OP wanted Read File From USB Drive. – Kusalananda Feb 2 '17 at 12:54
  • 1
    @Kusalananda, thank you for pointing it out. (I'm afraid I dont see that written in the question). In real situations (programming understanding, id words expanding, and CamelCase variants) it is common to use a basic criteria (either split in single Uppercase or the opposite) and have a dictionary of exceptions. – JJoao Feb 2 '17 at 16:51
  • 1
    Sorry, it was something the OP wrote in the comments to my answer. I agree, it's difficult to do this without a word list of some kind. – Kusalananda Feb 2 '17 at 16:53
2
sed -r -e "s/([^A-Z])([A-Z])/\1 \2/g"

Add space between a letter that is not an upper-case letter and a letter that is an upper-case letter

2
0

Python solution:

#!/usr/bin/env python
from __future__ import print_function
import sys

with open(sys.argv[1]) as f:
    for line in f:
        for char in line:
            if char.isupper():
               print(" "+char,end="")
            else:
               print(char,end="")

Test run:

$ ./add_space_to_upper.py input.txt                        
 Add Data
 Test Something
 Tell Me Who You Are
1
  • You want print(line[0], end="") followed by for char in line[1:]: to avoid printing that unwanted space at the beginning of every output line. – Paul Evans Feb 5 '17 at 12:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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