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
    Aug 9, 2016 at 21:50
  • @tomas it is true . 3 should be chaged to 1
    – zara
    Aug 9, 2016 at 21:52
  • @zara yes you're right, I updated my post.
    – user172564
    Aug 9, 2016 at 21:53
  • @tomas yes you're right, typo. I updated my post.
    – user172564
    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
    Aug 9, 2016 at 22:06
4

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
4

Here's an awk option:

awk -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 characters

  • 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

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.