Add spaces to the beginning of each matching line

2

For example, if I had a line that started at the beginning, and needed it to line up with the preceeding line, how could I do that most effectively.

      preceeding line
line I need to add spaces to

So it looks like this:

       predeeding line
       where it needs to start. 

Its exactly 8 spaces away from where it needs to start. How could I do this with vim, awk or sed or another tool?

Other requirements/notes:

These lines occur multiple times in my file and I only want to make the changes between lines 100-500.

user53029

Posted 2016-08-29T19:18:54.193

Reputation: 179

1Do you want all lines indented by 8 spaces? Or, do you want to match the indent on the preceding line? What if two or more non-indented lines appear in a row: should only the first be given an indent? Or, do they all get indents? – John1024 – 2016-08-29T19:27:30.553

Match the indent from the preceeding line. There should not be any non-indented lines that preceed the line I want to add, as long as we can match exactlly on the preceeding line. – user53029 – 2016-08-29T19:30:19.980

Let me clarify - there should not be any non-indented lines that would interfere, as long as we can match on the indented line to make the modification to the line below it. – user53029 – 2016-08-29T19:36:28.727

This looks like a simple case for Vim's auto indent. What happens when you start below the line with the correct indentation and call ==? To do this to 100-500 start at line 101 (assuming 100 has the correct indent) and then type 399== to auto indent the next 399 line like the one above it.

– Shadoath – 2016-08-30T16:43:00.560

Answers

1

Let's consider this test file:

$ cat file1
      preceeding line
line I need to add spaces to
    preceeding line
  preceeding line
line I need to add spaces to

The following indents the non-indented lines to match the indent of the previous line:

$ awk '{if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1
      preceeding line
      line I need to add spaces to
    preceeding line
  preceeding line
  line I need to add spaces to

How it works

  • if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}

    If the line starts with neither a blank nor a tab, the add the indent x to the start of the line.

    Else, save the indentation from the current line in variable x.

  • 1

    This is awk's cryptic shorthand for print-the-line.

Multi-line version

For those who prefer their code spread over multiple lines:

awk '
    {
        if (/^[^ \t]/) 
           $0=x $0
        else { 
            x=$0
            sub(/[^ \t].*/, "", x)
        }
    } 

    1' file1

Restricting the changes to lines 100 through 500

awk 'NR>=100 && NR<=500 {if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1

Changing the file in-place

Using GNU awk:

awk -i inplace 'NR>=100 && NR<=500 {if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1

Using BSD/OSX awk:

 awk 'NR>=100 && NR<=500 {if (/^[^ \t]/) $0=x $0; else {x=$0; sub(/[^ \t].*/, "", x);}} 1' file1 >tmp && mv tmp file1

John1024

Posted 2016-08-29T19:18:54.193

Reputation: 13 893

2

In vim:

:100,500g/^[^ ]/normal 0ky^jP

Explanation:

The "global" command in vim will apply an ex command to every line that matches a certain regex. This can be restricted a certain range of lines, in this case 100-500. The regex here is

^[^ ]

Which means any character except for a space at the beginning of the line. The ex command is

normal 0ky^jP

What this does:

0           "Move to the first character on this line
 k          "Move up one line
  y^        "Yank up to the first non-whitespace character
    j       "Move down one line
     P      "Paste what we just yanked

After running this, just call

:wq

To save your file and quit. You could also do this all from the command line:

vim myfile.txt -c "100,500g/^[^ ]/normal 0ky^jP" -c "wq"

Another alternate solution:

:%s/\v^(\s+).*\n\zs(\S)/\1\2

James

Posted 2016-08-29T19:18:54.193

Reputation: 632

0

Homework? ;->

sed -e '100,500s/^[ ]*/        /' -i file

Ipor Sircer

Posted 2016-08-29T19:18:54.193

Reputation: 3 578

Wouldn't this indent all lines and not just the ones I want? – user53029 – 2016-08-29T19:31:00.220

Yes, it would just add 8 spaces to the beginning of all lines, replacing any number of spaces currently present. – dr.nixon – 2016-08-29T20:01:20.437