6

My data looks like:

$ cat input
1212103122
1233321212
0000022221

I want the output to look like:

$ cat output
1 2 1 2 1 0 3 1 2 2
1 2 3 3 3 2 1 2 1 2
0 0 0 0 0 2 2 2 2 1

I tried:

sed -i 's// /g' input > output

but it does not work.

Any suggestions?

4 Answers 4

9

This worked for me:

sed 's/./& /g' input > output

$ cat input
1212103122
1233321212
0000022221

$ cat output
1 2 1 2 1 0 3 1 2 2 
1 2 3 3 3 2 1 2 1 2 
0 0 0 0 0 2 2 2 2 1 
5

Here you are:

sed 's/\(.\{1\}\)/\1 /g' input > output

And if you want to save the changes in-place:

sed -i 's/\(.\{1\}\)/\1 /g' input

How it works:

s/\(.\{1\}\)/\ /g will add a space, after each 1 character.

For instance, if you wanted an output file like:

12 12 10 31 22
12 33 32 12 12
00 00 02 22 21

You could edit my answer to:

sed -i 's/\(.\{2\}\)/\1 /g'

So it will add a space, after each 2 characters.

In addition, /\1 / is the same as /&, and will add one white-space. For instance, to add three: /\1 / or /& /. You have many more options to use. Sed is a super-powerful tool.

In addition yes, as @Law29 mentioned, this will leave a space at the end of each line if you do not remove, so to remove them while adding spaces you can add a s/ $// to the end of given solution, to do so:

sed 's/./& /g; s/ $//'

I hope this could help.

9
  • Not sed 's/\(.\{1\}\)/\1 /g' ?
    – user147505
    Commented Aug 9, 2016 at 21:50
  • @tomas it is true . 3 should be chaged to 1
    – zara
    Commented Aug 9, 2016 at 21:52
  • @zara yes you're right, I updated my post.
    – user172564
    Commented Aug 9, 2016 at 21:53
  • @tomas yes you're right, typo. I updated my post.
    – user172564
    Commented Aug 9, 2016 at 21:53
  • 2
    with -r you could remove most of the backslashes, making it more legible. {1} is not necessary, and if that is all you are matching then you don't even need to catch groups,
    – Law29
    Commented Aug 9, 2016 at 22:06
5

You have the -i option, which edits the file in place. This may have hindered you in finding the right solution.

Your problem is that you are trying to match an empty string, which sed will not allow. Instead, match any one character, and replace it with the same character followed by a space. This will leave you with a space at the end of each line, which you can remove with another sed.

$ cat input 
1212103122
1233321212
0000022221
$ sed -e 's/./& /g' -e 's/ $//' input > output
$ cat output
1 2 1 2 1 0 3 1 2 2
1 2 3 3 3 2 1 2 1 2
0 0 0 0 0 2 2 2 2 1
$ 
0
5

Here's an option with GNU awk:

gawk -F '' '{$1=$1}1' input > output

The principle of operation is:

  • by setting an empty field separator -F '', we split the input records (lines) into individual characters1

  • by evaluating $1=$1 we force the record to be re-built with the default output field separator (which is a single space)

  • 1 is true so print the result


A similar trick in perl:
perl -F'' -alne 'print join " ", @F' input > output

To illustrate:

$ awk -F '' '{$1=$1}1' input
1 2 1 2 1 0 3 1 2 2
1 2 3 3 3 2 1 2 1 2
0 0 0 0 0 2 2 2 2 1

  1. see Making Each Character a Separate Field in the The GNU Awk User's Guide
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .