5

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

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.

  • Not sed 's/\(.\{1\}\)/\1 /g' ? – Tomasz Aug 9 '16 at 21:50
  • @tomas it is true . 3 should be chaged to 1 – zara Aug 9 '16 at 21:52
  • @zara yes you're right, I updated my post. – FarazX Aug 9 '16 at 21:53
  • @tomas yes you're right, typo. I updated my post. – FarazX Aug 9 '16 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 '16 at 22:06
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 
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
$ 
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.