4
john    math
        science
paul    math
        science
rosy    math
jill    science
rob     math
        science
hary    math

Desired output:

john    math
john    science
paul    math
paul    science
rosy    math
jill    science
rob     math
rob     science
hary    math

2 Answers 2

5

Using awk, by acting upon number of fields

$ awk 'NF==1{print p "\t" $1; next} {p=$1} 1' ip.txt
john    math
john    science
paul    math
paul    science
rosy    math
jill    science
rob     math
rob     science
hary    math
  • {p=$1} 1 for lines other than single field, save first column and print the line
  • NF==1{print p "\t" $1; next} if only one field is present, print previous field, tab and the field from input line. next will skip rest of statements and process next line


if tab separation doesn't work out, use column

$ awk 'NF==1{print p,$1; next} {p=$1} 1' ip.txt | column -t
john  math
john  science
paul  math
paul  science
rosy  math
jill  science
rob   math
rob   science
hary  math
0

You can do it with sed this way:

sed ':n; N; s/\n[^ ]/&/; tsplit; s/^\([^ ]* *\)\([^ ]*\n\) *\([^ ]*\)$/\1\2\1\3/; :split; h; s/\n.*$//; p; g; s/^.*\n//; bn' test.txt

Explanation

sed '# Start label for loop
:n
# Read next string to main buffer, separated by "\n"
N
# Split and print first string if second starts with non-space character
s/\n[^ ]/&/
tsplit
# "^\([^ ]* *\)" -- First word with spaces, \1.
# "\([^ ]*\n\)"  -- Second word, \2.
# " *"           -- Spaces in second line, throw them.
# "\([^ ]*\\)"   -- Second word in second line, \3.
s/^\([^ ]* *\)\([^ ]*\n\) *\([^ ]*\)$/\1\2\1\3/
# Splitting
:split
# Send both lines to hold buffer
h
# Delete second line, print first
s/\n.*$//
p
# Lines to main buffer, delete first.
g
s/^.*\n//
# Now second file is first, start loop again.
bn' test.txt

You must log in to answer this question.

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