awk sed to repeat every character on same position from the upper line replacing whitespace

Hello is it possible with awk or sed to replace any white space with the previous line characters in the same position?

I am asking this because the file I have doesn't always follow a pattern.
For example the file I have is the result of a command to obtain windows ACLs:
icacls C:\ /t >output.txt

The order, number of lines that start with whitespace but have some text will change.

t e s t string 1 2 3 4 5
        sample a b c d e
        othersample 1 2 3 4 5

Should say

t e s t string 1 2 3 4 5
t e s t sample a b c d e
t e s t othersample 1 2 3 4 5

Another example: 
text 1 string 9 7 8 6
       something x \ / x
       something else 1 1 1 1 1 1 1 1

Same as before
text 1 string 9 7 8 6
text 1 something x \ / x
text 1 something else 1 1 1 1 1 1 1 1


I don't get it, why shouldn't the output be:

t e s t string 1 2 3 4 5
t e s t sample a b c d e
t e s t othersamplec1d2e3 4 5

and:

text 1 string 9 7 8 6
text 1 something7x8\6/ x
text 1 something7else/1x1 1 1 1 1 1 1

You say "whitespace". Are there tabs in the input you're processing or just spaces? If there are tabs, are they to be treated as a single whitespace character, or are they to be treated as one to eight space characters (assuming tab stops are set on every 8th position) depending on where they are located on an input line?

What operating system and shell are you using?

What have you tried to solve this problem on your own?

I only need the text/string until there is a character that is not a whitespace on that line. If there is already data in there I do not want to modify that.

I am afraid there is no tab, only spaces.

I am on Windows using awk and sed

I tried to obtain the leading whitespaces:
awk -F'[^ \t]' '{print length($1)}' now I am trying to obtain that number of characters from the line above where I find whitespaces

Building on what you had come up with, try:

awk -F'[^ ]' '
{	current_len = length($1)
	last_len = length(last_line)
	len = current_len > last_len ? last_len : current_len
	last_line = substr(last_line, 1, len) substr($0, len + 1)
	print last_line
}' file

Note that this code resets itself when it sees an empty line. So, with the following in a file named file :

t e s t string 1 2 3 4 5
        sample a b c d e
        othersample 1 2 3 4 5

text 1 string 9 7 8 6
       something x \ / x
                 else 1 1 1 1 1 1 1 1

the above code produces the output:

t e s t string 1 2 3 4 5
t e s t sample a b c d e
t e s t othersample 1 2 3 4 5

text 1 string 9 7 8 6
text 1 something x \ / x
text 1 something else 1 1 1 1 1 1 1 1

which I think matches what you want.

If someone else wants to try this on a Solaris/SunOS system, change awk to nawk or /usr/xpg4/bin/awk .

1 Like
awk -F'[^ ]' '
{	current_len = length($1)
	last_len = length(last_line)
	len = current_len > last_len ? last_len : current_len
	last_line = substr(last_line, 1, len) substr($0, len + 1)
	print last_line
}' file

Thanks a lot, it worked perfectly.
I saved it as an awk file as I am on Windows to avoid the conversion/adaptation and I am launching as a .awk file and it works perfectly

You may want to try

awk '
1 == match ($0, "[^     ]")     {ORG = $0
                                }
                                {IX = index ($0, "      ")
                                 IX = RSTART + (IX?8:0) - IX
                                 print substr (ORG, 1, IX - 1) substr ($0, RSTART) 
                                }
' file

as well. It behaves slightly different from Don Cragun's proposal, but, if need be, can be easily adapted to behave the same. It doesn't need an empty line to recognize a new pattern, though.

1 Like