substitui o valor em branco pelo valor anterior da primeira coluna usando awk e sed

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

Saída desejada:

john    math
john    science
paul    math
paul    science
rosy    math
jill    science
rob     math
rob     science
hary    math
    
por shachi 24.12.2016 / 08:05

2 respostas

5

Usando awk , agindo sobre o número de campos

$ 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 para linhas diferentes do campo único, salve a primeira coluna e imprima a linha
  • NF==1{print p "\t" $1; next} se apenas um campo estiver presente, imprima campo anterior, tab e o campo da linha de entrada. next pulará o restante das instruções e processará a próxima linha


Se tab separação não funcionar, 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
    
por 24.12.2016 / 08:19
0

Você pode fazer isso com sed desta maneira:

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

Explicação

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, .
# "\([^ ]*\n\)"  -- Second word, .
# " *"           -- Spaces in second line, throw them.
# "\([^ ]*\)"   -- Second word in second line, .
s/^\([^ ]* *\)\([^ ]*\n\) *\([^ ]*\)$//
# 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
    
por 04.01.2017 / 16:01