0

I have a file with Feature names and a variable number of usernames below:

Feature1

user1

user2

Feature2

user3

I'd like to be able to move the usernames to the same line as the Feature name (along the lines of the vi join command). The Feature names begin with an uppercase letter and the usernames begin with lowercase. Is there a way to do this?

3 Answers 3

3

That's pretty easy with sed:

sed ':a;N;$!ba;s/\n\+\([a-z]\)/ \1/g;'

Small description how it works:

:a;N;$!ba; will add all lines into match pattern. we need it to delete all newlines in the next step. s/\n\+\([a-z]\)/ \1/g; will delete all newlines before user* and save newlines before Feature*. btw it also can be done with

tr '\n' ' ' | sed 's/ \([A-Z]\)/\n\1/g'


 $ cat test_file
Feature1

user1

user2
Feature2

user3
Feature2
user3
user3

ouser3

user3

 $ sed ':a;N;$!ba;s/\n\+\([a-z]\)/ \1/g;' test_file
Feature1 user1 user2
Feature2 user3
Feature2 user3 user3 ouser3 user3
3
  • Mind adding some discussion about what each step of the sed statement is doing? Sed is a powerful but hard to grok beast sometimes.
    – Red Tux
    Jun 26, 2012 at 22:09
  • I've added small description. Hope now it's a little bit clear.
    – rush
    Jun 27, 2012 at 5:15
  • 1
    Heh. sed is one of the tools that makes some of my colleagues go "What kind of wizardry is this!!" mode. Nicely done, Rush! :) Jun 27, 2012 at 5:28
1

It's very straightforward in AWK:

awk '/^[[:upper:]]/ {if (line) {print line}; line = $0} /^[[:lower:]]/ {line = line " " $0} END {if (line) {print line}}'
0

You will want to chunk your data before writing it. Something like the following pseudocode (you will need to make this into proper BASH syntax yourself).

out_line=""
for in_line in $(cat $file); do
  if $(echo in_line | egrep ^Feature) != ""
    echo $out_line >> $out_file
    out_line="$in_line"
  else
    out_line="$out_line $in_line"
  fi
done
echo $out_line >> $out_file
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .