Sergi
Sergi

Reputation: 417

Sed substitution for text

I have this kind of text:

0
4.496
4.496
Plain text.
7.186
Plain text
10.949
Plain text
12.988
Plain text
16.11
Plain text
17.569
Plain text
ESP:
Plain text

I am trying to make a sed substitution because I need all aligned after the numbers, something like:

0
4.496
4.496 Plain text.
7.186 Plain text
10.949 Plain text
12.988 Plain text
16.11 Plain text
17.569 Plain text ESP:Plain text

But I'm trying with different combinations of commands with sed but I can't keep a part of the matching pattern

sed -r 's/\([0-9]+\.[0-9]*\)\s*/\1/g'

I am trying to remove all \n after the numbers and align the text, but it does not work. I need to align text with text too.

I tried this as well:

sed -r 's/\n*//g'

But without results.

Thank you

Upvotes: 1

Views: 239

Answers (4)

potong
potong

Reputation: 58568

This might work for you (GNU sed):

sed ':a;N;s/\n\([[:alpha:]]\)/ \1/;ta;P;D' file

Process two lines at a time. If the second line begins with an alphabetic character, remove the preceeding newline and append another line and repeat. If the second line does not begin with an alphabetic character, print and then delete the first line and its newline. The second line now becomes the first line and the process repeats.

Upvotes: 1

anubhava
anubhava

Reputation: 786091

This gnu-awk command can also handle this:

awk -v RS= 'BEGIN{ FPAT="(^|\n)[0-9]+(\\.[0-9]+)?(\n[^0-9][^\n]*)*" }
   {for (i=1; i<=NF; i++) {f=$i; sub(/^\n/, "", f); gsub(/\n/, " ", f); print f}}' file
0
4.496
4.496 Plain text.
7.186 Plain text
10.949 Plain text
12.988 Plain text
16.11 Plain text
17.569 Plain text ESP: Plain text

Upvotes: 2

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed -n '1h;1!H;$!b
         x;s/\n\([^0-9]\)/ \1/gp' YourFile
  • -n: print only at demand
  • '1h;1!H;$!b;xload the whole file in buffer until the end (at the end the whole file is in work buffer)
  • s/\n\([^0-9]\)/ \1/gp: replace all new line followed by a non digit character by a space character and print the result.

Upvotes: 1

Wintermute
Wintermute

Reputation: 44063

This is a bit tricky. Your approach does not work because sed operates in a line-based manner (it reads a line, runs the code, reads another line, runs the code, and so forth), so it doesn't see the newlines unless you do special things. We'll have to completely override sed's normal control flow.

With GNU sed:

sed ':a $!{ N; /\n[0-9]/ { P; s/.*\n//; }; s/\n/ /; ba }' filename

This works as follows:

:a                # Jump label for looping (we'll build our own loop, with
                  # black jack and...nevermind)
$! {              # Unless the end of the input was reached:
  N               # fetch another line, append it to what we already have
  /\n[0-9]/ {     # if the new line begins with a number (if the pattern space
                  # contains a newline followed by a number)
    P             # print everything up to the newline
    s/.*\n//      # remove everything before the newline
  }
  s/\n/ /         # remove the newline if it is still there
  ba              # go to a (loop)
}
                  # After the end of the input we drop off here and implicitly
                  # print the last line.

The code can be adapted to work with BSD sed (as found on *BSD and Mac OS X), but BSD sed is a bit picky about labels and jump instructions. I believe

sed -e ':a' -e '$!{ N; /\n[0-9]/ { P; s/.*\n//; }; s/\n/ /; ba' -e '}' filename

should work.

Upvotes: 2

Related Questions