1

Is it possible to transform:

John Apple Red 3
John Apple Green 5
John Radish White 2
John Radish Red 7
Tom Apple Red 3
Tom Apple Green 5
Tom Radish White 2
Tom Radish Red 7

to:

John Apple Red 3
           Green 5
     Radish White 2
            Red 7
Tom Apple Red 3
          Green 5
    Radish White 2
           Red 7

using Vim?


I have a large block of configurations (~10k). Each one is something like

Criterion1=1A Criterion2=2A Criterion3=3A... ConfigItem=valA
Criterion1=1A Criterion2=2A Criterion3=3B... ConfigItem=valB
Criterion1=1A Criterion2=2B Criterion3=3C... ConfigItem=valC
Criterion1=1A Criterion2=2B Criterion3=3D... ConfigItem=valD
Criterion1=1B Criterion2=2E Criterion3=3F... ConfigItem=valE

I'm hoping to simplify the presentation to better understand it. Here's an example:

Criterion1=1A Criterion2=2A Criterion3=3A... ConfigItem=valA
                            Criterion3=3B... ConfigItem=valB
              Criterion2=2B Criterion3=3C... ConfigItem=valC
                            Criterion3=3D... ConfigItem=valD
Criterion1=1B Criterion2=2E Criterion3=3F... ConfigItem=valE

The format I've demonstrated above (replacing common repeated prefixes with spaces) would also help make folding work.

4
  • 1
    What did you try?
    – romainl
    Sep 13, 2023 at 5:42
  • [[1]] It is not "characters" , it should be "words" [[2]] You should include why you want to try this , because there might be "better" ways to achieve that
    – Prem
    Sep 13, 2023 at 11:53
  • i dump from a piece of code a bunch of configurations (>10k), each one is something like Criterion1=Value1 Criterion2=Value2 Criterion3=Value3 ... -> ConfigName=ConfigValue, now it's a long txt file, somewhat overwhelming, I'm looking to simplify it as the example above, what's more, the blank spaces would help in folding as i'm using vim.
    – athos
    Sep 13, 2023 at 17:03
  • @romainl I don't know how to start, not familiar with (advanced) regex. honestly Vivian's answer I don't quite get how the (.*) part matched the next line. currently I'm only using block editing to select some rows with common starting words, and then r to replace that part with space.
    – athos
    Sep 13, 2023 at 17:06

1 Answer 1

1

I would run the following commands:

:g/^./move 0
:%s/\v^(.*)\ze.*\n\1/\=substitute(submatch(1), '.', ' ', 'g')
:g/^./move 0
  1. g/^./move 0 moves the text upside down. Since the logic has to run from bottom to top but substitution only works from top to bottom I first move the buffer upside down.

  2. s/\v^(.*)\ze.*\n\1 splits the current line into: the part that is in common with the next line ((.*)) and the part that is not (.*)

    Remark: I use \ze to:

    1. avoid that the pattern eats part of the next line, otherwise the substitution will apply only on one line out of two and
    2. avoid it eats the second part of the line such that we don't need to replace it.
  3. substitute(submatch(1), '.', ' ', 'g') replaces every character of the first part by a space

  4. g/^./move 0) restores the lines in the right order.

9
  • 2
    Let me guess, you're going to add an explanation of what this does after it gets accepted?
    – Friedrich
    Sep 13, 2023 at 6:05
  • 1
    No I publish a first version quickly for the impatient :-) Sep 13, 2023 at 6:11
  • i might be asking too much, is it possible to make the comparision not by characters but by word?
    – athos
    Sep 13, 2023 at 16:22
  • I thought about it but it is for sure more complex and probably require more command. If I find a solution I'll post it ;-) Sep 13, 2023 at 16:34
  • thank you very much!
    – athos
    Sep 13, 2023 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.