5

I'm trying to insert a space between letters only, not numbers or other characters.

hello woRLd 12ab34 should become h e l l o w o R L d 12a b34

sed 's/\([a-zA-Z]\)\([a-zA-Z]\)/\1 \2/g' file.txt

results in h el lo w or LD 12a b34

I can't insert a space after every letter, as that doesn't check if the one after that will be a letter also.

I could run the sed command twice, which solves the problem but is not elegant. I need to solve this problem using sed, if possible.

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • Depending on your definition of letters and your locale, you may want to use [[:alpha:]] instead of [a-zA-Z] – Philippos Jul 22 '22 at 05:42

3 Answers3

6

You could do it using a loop + conditional branch:

$ echo "hello woRLd 12ab34" | sed '
:a
s/\([a-zA-Z]\)\([a-zA-Z]\)/\1 \2/
ta
'
h e l l o w o R L d 12a b34

or more compactly

$ echo "hello woRLd 12ab34" | sed -e :a -e 's/\([a-zA-Z]\)\([a-zA-Z]\)/\1 \2/' -e ta
h e l l o w o R L d 12a b34
steeldriver
  • 81,074
5

You don't need to run the sed command twice, you can simply run the substitute command inside the sed script twice. sed has an elegant way to do this: The empty pattern // repeats the previous pattern:

sed 's/\([a-zA-Z]\)\([a-zA-Z]\)/\1 \2/g;s//\1 \2/g' file.txt

For the sake of readability, I suggest to use extended regular expressions:

sed -E 's/([a-zA-Z])([a-zA-Z])/\1 \2/g;s//\1 \2/g' file.txt
Philippos
  • 13,453
0

You just need a single regex using lookahead. Unfortunately sed doesn't support lookarounds so you need to use perl

$ echo "hello woRLd 12ab34" | perl -pe 's/([a-zA-Z])(?=[a-zA-Z])/\1 /g'
h e l l o w o R L d 12a b34

$ perl -pe 's/([a-zA-Z])(?=[a-zA-Z])/\1 /g' file.txt h e l l o w o R L d 12a b34

Use perl -pne if there are multiple input lines to process and perl -i -pe to edit the file in-place

phuclv
  • 2,086