0

Is it possible to insert new lines in order to line up the contents of a file?

I have:

1:1   Lorem ipsum dolor sit amet consectetur    1:1   This is sample text of varying length.
      adipiscing elit.                          1:2   This is another paragraph in this file.
1:2   Vivamus integer non suscipit taciti mus         Yet another sentence in this paragraph.
      etiam at primis tempor sagittis.          1:3   Another paragraph can be found here!

How can I add spaces appropriately so that the numbers line up?

Expected output:

1:1   Lorem ipsum dolor sit amet consectetur          This is sample text of varying length.
      adipiscing elit.                          
1:2   Vivamus integer non suscipit taciti mus         This is another paragraph in this file.    
      etiam at primis tempor sagittis.                Yet another sentence in this paragraph.
1:3                                                   Another paragraph can be found here!

Edit: since the lines would be lined up, there is no need for the numbers to be repeated so they can be removed.

POSIX compliance is preferred.

7
  • Is there any particular logic where 1:2 This... needs to be broken out of it's current line and appended to the next line? Same for 'Another paragraph...` being added to it's on unique line. We'll need the rules in order to create a script.
    – doneal24
    Commented Jul 6, 2022 at 17:45
  • @doneal24 It seems it's the paragraph labels, 1:1, 1:2 etc., that should be aligned on the same lines in the left and right column of text. So we would need to come up with a way to parse the left and right columns more or less separately, and then align them for output based on the labels.
    – Kusalananda
    Commented Jul 6, 2022 at 17:48
  • Yeah it's the paragraph labels. Essentially corresponding lines should be aligned
    – Venem
    Commented Jul 6, 2022 at 17:52
  • @Kusalananda I'm not sure this is really defined. Should ...1:3 Another paragraph be translated to ^1:3 Another paragraph? How do you handle the second #:# tag when it has not been previously used?
    – doneal24
    Commented Jul 6, 2022 at 17:55
  • Just chiming in here, you could use something like awk to check if fields x and y (the numbers) are equal to each other. For 1:3, field x would be empty since we're not defining a third paragraph on the left. You could detect this and add an empty line there (with 1:3 moved to the start of the line). This should also work if the right column is missing a field but instead add the blank space there.
    – Venem
    Commented Jul 6, 2022 at 18:08

1 Answer 1

3

Using GNU awk to read the text as a fixed-width set of records, where each record is divided into fields of widths 6 (left label), 42 (left line of text), 6 (right label), and 42 (right line of text):

BEGIN {
        FIELDWIDTHS = "6 42 6 42"
}

# New label seen on the left hand side.
# If this is a completely new label, then
# add it to the end of the "labels" array.
$1 != "      " {
        llabel = $1
        if (!seenlabels[llabel]++)
                labels[++n] = llabel
}

# Same as above, but for the right hand side.
$3 != "      " {
        rlabel = $3
        if (!seenlabels[rlabel]++)
                labels[++n] = rlabel
}

# Add text to the labelled paragraphs, left and right,
# as strings delimited by ORS (newline).
{
        ltext[llabel] = (ltext[llabel] == "" ? $2 : ltext[llabel] ORS $2)
        rtext[rlabel] = (rtext[rlabel] == "" ? $4 : rtext[rlabel] ORS $4)
}

# At end, output.
END {
        # Iterate over all paragraphs (there are "n" of them).
        for (i = 1; i <= n; ++i) {
                delete llines
                delete rlines

                # Split the text for the left and right paragraph,
                # into arrays, "llines" and "rlines".
                a = split(ltext[labels[i]], llines, ORS)
                b = split(rtext[labels[i]], rlines, ORS)

                # The arrays may be of different lengths, but
                # "c" will be the length of the longest, i.e.
                # the number of lines of the paragraph to the
                # left or right, whichever is longes.
                c = (a > b ? a : b)

                # Print the first line of the left and right
                # of this paragarph (includes the label at the left).
                printf("%-6s%-42s%-6s%-42s\n", labels[i], llines[1], "", rlines[1])

                # Then print the other lines (no label).
                for (j = 2; j <= c; ++j)
                        printf("%-6s%-42s%-6s%-42s\n", "", llines[j], "", rlines[j])
        }
}

Testing:

$ cat file
1:1   Lorem ipsum dolor sit amet consectetur    1:1   This is sample text of varying length.
      adipiscing elit.                          1:2   This is another paragraph in this file.
1:2   Vivamus integer non suscipit taciti mus         Yet another sentence in this paragraph.
      etiam at primis tempor sagittis.          1:3   Another paragraph can be found here!
$ gawk -f script file
1:1   Lorem ipsum dolor sit amet consectetur          This is sample text of varying length.
      adipiscing elit.
1:2   Vivamus integer non suscipit taciti mus         This is another paragraph in this file.
      etiam at primis tempor sagittis.                Yet another sentence in this paragraph.
1:3                                                   Another paragraph can be found here!

Since this is using GNU-specific extensions to the POSIX specification of awk (the FIELDWIDTHS variable), it is not a strictly POSIX answer.

For a POSIX compliant answer just replace the BEGIN section with:

{
    rec = $0
    $0 = ""
    $1 = substr(rec,1,6)
    $2 = substr(rec,7,42)
    $3 = substr(rec,49,6)
    $4 = substr(rec,55)
}
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .