0
Sample Input:
James  account
       note
       money
Ruby   account
       money
Taylor account
       note
Rob    money


Desired Output:

James  account
James  note
James  money
Ruby   account
Ruby   money
Taylor account
Taylor note
Rob    money  

As you notice in the above output, all the blank spaces in first-column are filled with value obtained from previous non-empty line. I am using KSH, Linux x86. I prefer awk, sed.

3

Something like

awk 'NF>1 {x=$1; print; next} {print x,$1}' Input
James  account
James note
James money
Ruby   account
Ruby money
Taylor account
Taylor note
Rob    money

If you want to prettify the alignment of the output, pipe it through column -t

1
$ awk 'NF == 1 { $2 = $1; $1 = col1 } { col1 = $1; print }' file
James  account
James note
James money
Ruby   account
Ruby money
Taylor account
Taylor note
Rob    money

If the number of whitespace-delimited fields on the current line is one (NF == 1), then move the contents of the first field into the second (which is empty), then assign the value saved in col1 to the first field.

For all lines, save the value of the first field into col1 and print.

0

One way with GNU sed is as following:

sed -re '                       ;# invoke GNU sed with extended regex engine
    /\S\s+\S/N                  ;# append the next line into the PS for multi-field lines
    s/^((\S+\s+).*\n)\s+/\1\2/  ;# stick the first two fields from 1st line to 2nd
    P;D                         ;# print multi-field line, & the 2nd line too now is multi-field
' input.file

Output:

James  account
James  note
James  money
Ruby   account
Ruby   money
Taylor account
Taylor note
Rob    money

Constraints:

  1. The input with multi-field line mustn't begin with blanks/spaces.
  2. GNU sed supporting extended regexes needed, although this code can be reworded to be POSIXly.
0

Using cut and tr:

while IFS=$'\n' read -r line
do
    if printf -- '%s\n' "$line" | grep -E -q '^[[:blank:]]'
    then
        # is blank
        word="$(printf -- '%s\n' "$line" | tr -d '[:blank:]')"
        printf -- '%s %s\n' "$prefix" "$word"
    else
        # is not blank
        prefix="$(printf -- '%s\n' "$line" | cut -d ' ' -f 1)"
        printf -- '%s\n' "$line" | tr -s ' '
    fi
done < file

Output:

James account
James note
James money
Ruby account
Ruby money
Taylor account
Taylor note
Rob money

Then, it can be padded with column -t, as mentioned.

Alternatively, without column:

length=0
while read -r line
do
    cur_length="$(printf -- '%s\n' "$line" | cut -d ' ' -f 1 | wc -c)"
    [ "$cur_length" -gt "$length" ] && length="$cur_length"
done < file

while IFS=$'\n' read -r line
do
    if printf -- '%s\n' "$line" | grep -E -q '^[[:blank:]]'
    then
        # is blank
        word="$(printf -- '%s\n' "$line" | tr -d '[:blank:]')"

        printf -- "%-${length}s%s\n" "$prefix" "$word"
    else
        # is not blank
        prefix="$(printf -- '%s\n' "$line" | cut -d ' ' -f 1 | \
          tr -d '[:blank:]')"

        suffix="$(printf -- '%s\n' "$line" | cut -d ' ' -f 2- | \
          tr -d '[:blank:]')"

        printf -- "%-${length}s%s\n" "$prefix" "$suffix"
    fi
done < file

Output:

James  account
James  note
James  money
Ruby   account
Ruby   money
Taylor account
Taylor note
Rob    money

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.