1

I have a large file ~/foo.txt. Thousands of lines of the form

SIZE : X  Y

are scattered throughout the file where X and Y are integers. My problem is that sometimes the integers X and Y are separated by two spaces and sometimes they are separated by one space. I would like to write a perl script that makes the spacing consistent, preferably with two spaces. How could I go about this?

3
  • Must it be sed? In bash I would do "tr -s " " < ~/foo.txt > dest.txt" for one spacing. – Rui F Ribeiro Dec 2 '15 at 7:23
  • This works, I suppose, but there are other instances of consecutive spaces in the file that I would like to preserve, if possible. – Brian Fitzpatrick Dec 2 '15 at 7:26
  • I don't really care about the tool to be honest. I just assumed perl would be good for this. – Brian Fitzpatrick Dec 2 '15 at 7:31
3

You say integers, but I suspect you mean positive numbers. Here is a rough quick attempt at a solution:

sed 's/\([0-9]\+\)\s\+\([0-9]\+\)/\1  \2/g'

There are caveats here, such as if the second number starts with a negative sign, or if there are spaces you don't want handled like this that occur between, for instance, a53 and 27B. Or if you don't want all numbers to be separated by two spaces. But this is a start that you can modify as you will.


Rereading your question, it appears that all of the spaces you want to "squeeze" occur specifically on lines starting with the word "SIZE". This makes it much simpler. You say "other instances of consecutive spaces" you want to preserve, but it sounds like those are on other lines. So in that case just use:

sed '/^SIZE/ s_\s\s\+_  _'

(There are two spaces in the replacement text.)


Rereading again, I now see you want to fix one space to two spaces. This gets a bit more dependent on the exact format of your lines, but I would say:

sed '/^SIZE/ s_\s\+_  _3'

should do it. (It works on the sample you provide.) The 3 makes the substitution only occur on the 3rd match of \s\+ - which, as chaos explained, means "one or more space or tab". So in SIZE<space>:<space>X<space>Y, it will turn the space in between the X and Y into two spaces.

2
  • Yes. Obviously, I started at least 14 seconds later... =) Anyway +1, but no need for the g. – chaos Dec 2 '15 at 7:34
  • Thank you and good point. I upvoted yours; good for including the full explanation, I tend to get lazy about that. – Wildcard Dec 2 '15 at 7:40
1

With sed:

sed -i 's/\([0-9]\)\s\+\([0-9]\)/\1  \2/' file
  • -i edits the file inplace.
  • [0-9]: seaches for a digit.
  • \s+: this digit is followed by a space or tab.
  • [0-9]: and again followed by a digit.
  • \1 \2 those two digits are saved in the backreferences \1 and \2 which are now separated by two spaces.

Example:

$ cat file
SIZE : 2  1 # 2 spaces
SIZE : 1 22 # 1 space
SIZE : 1    1 # 4 spaces
SIZE : 324  34 # a tab
SIZE : 324      34 # 2 tabs
$ sed 's/\([0-9]\)\s\+\([0-9]\)/\1  \2/' file
SIZE : 2  1
SIZE : 1  22
SIZE : 1  1
SIZE : 324  3
SIZE : 324  34
1
  • Ah! Ninja'd by 13 seconds. :) – Wildcard Dec 2 '15 at 7:32
0
sed 's/\([0-9] \) *\([-+.]*[0-9]\)/\1 \2/g' <in >out

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.