0

In a file like:

ruler    1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
\usage{
function(
parameter,
parameterparameter,
parameter = parameter,
parameter = p,
parameter = para,
parameter = para,
paramete = p,
parameterparameter = pa,
parameter = p,
p = pa,
param,
parameterpara = par,
paramet = par,
parameter = param,
parameterpa = param,
...
more lines

I want to concatenate lines from line with "usage" to the line with "...", and then, create new line breaks after commas before the 80th character (column).

For now, I manage to break lines after the nth comma, but it is not efficient because in many cases a lot of spaces remain after, say, the 3rd comma. So I want the comma before the line break to be as close as possible to the 80th character.

sed -i -r '/usage/{:a;N;/\.\.\./!ba;s/\n//g}' filename.txt
sed -i 's/\(\([^,]\+,\)\{3\}\)/\1\n/g;s/\n/\n/g' filename.txt

I looked at "par", "fold" and "fmt" documentation without success. "fold" gets near but splits lines in space not comma:

sed -i -r '/usage/{:a;N;/\.\.\./!ba;s/\n//g}' filename.txt
fold -s filename.txt | tee filename.txt
  • 2
    Please edit your question and show us what output you expect from this input file so we can understand exactly what you need. – terdon Apr 11 at 14:23
  • Please show us the actual output you want, not a command that produces something "similar". We need to know what you need in order to be able to help you, don't make us guess. – terdon Apr 11 at 15:46
  • Also, sorry, I just rejected your suggested edit to Stéphane's answer because I didn't realize it was you, the question asker, who suggested it. Sorry! – terdon Apr 11 at 15:49
1

A lazy variant, using perl's slurp mode:

perl -0777 -pi -e '
  s{\\usage.*?\n\.\.\.\n}{
    ($r = $&) =~ s/\n//g;
    $r =~ s/\G.{0,79}(,|.$)\K/\n/g;
    $r
  }gse' your-file

Which gives:

         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
\usage{function(parameter,parameterparameter,parameter = parameter,
parameter = p,parameter = para,parameter = para,paramete = p,
parameterparameter = pa,parameter = p,p = pa,param,parameterpara = par,
paramet = par,parameter = param,parameterpa = param,...
more lines
| improve this answer | |
  • 1
    Why did you add an extra line of numbers to the question? That changes the OP's file. Is that line actually present? If not, please undo that edit, we shouldn't change the OP's data since you never know how that could affect an answer. – terdon Apr 11 at 15:47
  • 1
    @terdon, that's a ruler to show where the 80th column is. It's easier to read with that extra line. I don't expect that line is part of the input. – Stéphane Chazelas Apr 11 at 15:57
  • could you comment the code? – Ferroao Apr 13 at 21:16
2

Using awk:

$ awk '/^\\usage/,/^\.\.\./ { if (length(line $0) >= 80) { print line; line = $0 } else line = line $0; next  }; line != "" { print line; line = "" }; 1' file
         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
\usage{function(parameter,parameterparameter,parameter = parameter,
parameter = p,parameter = para,parameter = para,paramete = p,
parameterparameter = pa,parameter = p,p = pa,param,parameterpara = par,
paramet = par,parameter = param,parameterpa = param,...
more lines

The awk code, annotated:

/^\\usage/,/^\.\.\./ {
        # This block triggers for all lines between a line
        # starting with "\usage" and another line
        # starting with "..."

        # If our saved output line and the current line together
        # is longer or equal to 80 characters, print the output
        # line and reset it to the current line.  Else, add the
        # current line to the end of the saved output line.
        if (length(line $0) >= 80) {
                print line
                line = $0
        } else
                line = line $0

        # Skip to next line of input.
        next
}

# If we get here and the saved output line is
# non-empty, then there is data to output, so
# do that.
line != "" { print line; line = "" }

# Print all input.
1
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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