abasu
abasu

Reputation: 2524

sed right align a group of text

this question originated from string pattaren-matching using awk , basically we are splitting a line of text in multiple groups based on a regex pattern, and then printing two groups only. Now the question is can we right align a group while printing through sed? below is an example

$cat input.txt
it is line one
it is longggggggg one
itttttttttt is another one

now

$sed -e 's/\(.*\) \(.*\) \(.*\) \(.*\)/\1 \3/g' input.txt

it splits and prints group 1 and 3, but the output is

it line
it longggggggg
itttttttttt another

my question is can we do it through sed so that the output comes as

it                             line
it                      longggggggg
itttttttttt                 another

I did it with awk but I feel it can be done through sed, but I am not able to get how I am going to get the length of the second group and then pad correct number of spaces in between the groups, I am open to any suggestions to try out.

Upvotes: 0

Views: 2581

Answers (6)

BobDodds
BobDodds

Reputation: 23

Del columns 2 and 4. Right justify resulting col 2 at line length of 23 chars.

sed -e '
 s/[^ ]\+/                       /4;
 s/[^ ]\+//2;
 s/^\(.\{23\}\).*$/\1/;
 s/\(^[^ ]\+[ ]\+\)\([^ ]\+\)\([ ]\+\)/\1\3\2/;
'

or gnu sed with extended regex:

sed -r '
 s/\W+\w+\W+(\w+)\W+\w+$/\1                       /;
 s/^(.{23}).*/\1/;
 s/(+\W)(\w+)(\W+)$/\1\3\2/
'

Upvotes: 0

Yunnosch
Yunnosch

Reputation: 26703

This question is old, but I like to see it as a puzzle. While I love the loop solution for its brevity, here is one without a loop or shell help.

sed -E "s/ \w+ (\w+) \w+$/ \1/;h;s/./ /g;s/$/#                       /;s/( *)#\1//;x;H;x;s/\n//;s/^( *)(\w+)/\2\1/"

or without extended regex

sed "s/ .* \(.*\) .*$/ \1/;h;s/./ /g;s/$/#                       /;s/\( *\)#\1//;x;H;x;s/\n//;s/^\( *\)\([^ ]*\)/\2\1/"

Upvotes: -1

potong
potong

Reputation: 58381

This might work for you (GNU sed):

sed -r 's/^(.*) .* (.*) .*$/\1 \2/;:a;s/^.{1,40}$/ &/;ta;s/^( *)(\S*)/\2\1/' file

or:

sed -r 's/^(.*) .* (.*) .*$/printf "%-20s%20s" \1 \2/e' file

Upvotes: 2

NeronLeVelu
NeronLeVelu

Reputation: 10039

TemplateSpace="                                                      "
TemplateSize=${#TemplateSpace}

sed "
# split your group (based on word here but depend on your real need)
s/^ *\(\w\) \(\w\) \(\w\) \(\w\).*$/\1 \3/

# align
s/$/${TemplateSpace}/
s/^\(.\{${TemplateSize}\}\).*$/\1/
s/\(\w\) \(\w\)\( *\)/\1 \3\2/
"

or more simple for avoiding TemplateSize (and there are no dot in content)

TemplateSpace="............................................................."

and replace

s/^\(.\{${TemplateSize}\}.*$/\1/ 

by

s/^\(${TemplateSpace}\).*$/\1/
s/\./ /g

Upvotes: 0

Idriss Neumann
Idriss Neumann

Reputation: 3838

It most easy to use awk in this case...

You could too use a bash loop to calculate the number of space and run this command on the line covered :

while read; do
    # ... calculate $SPACE ...
    echo $REPLY|sed "s/\([^\ ]*\)\ *[^\ ]*\ *\([^\ ]*\)/\1$SPACES\2/g"
done < file

But I prefer use awk for do all that (or other advanced shell languages ​​such as Perl, Python, PHP shell mode, ...)

Upvotes: 0

halfbit
halfbit

Reputation: 3464

You can use looping in sed to achieve what you want:

#!/bin/bash
echo 'aa bb cc dd
11 22 33333333 44
ONE TWO THREEEEEEEEE FOUR' | \
sed -e 's/\(.*\) \(.*\) \(.*\) \(.*\)/\1 \3/g' \
-e '/\([^ ]*\) \([^ ]*\)/ { :x ; s/^\(.\{1,19\}\) \(.\{1,19\}\)$/\1  \2/g ; tx }'

The two 19's control the width of your columns. The :x is a label which is looped to by tx whenever the preceding substitution succeeded. (You could add a p; before tx to "debug" it.

Upvotes: 1

Related Questions