Zeilenumbrüche nach Kommas erstellen - vor der gewünschten Zeilenbreite

Zeilenumbrüche nach Kommas erstellen - vor der gewünschten Zeilenbreite

In einer Datei wie:

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

Ich möchte Zeilen von der Zeile mit „Verwendung“ bis zur Zeile mit „…“ verketten und dann vor dem 80. Zeichen (Spalte) neue Zeilenumbrüche nach Kommas erstellen.

Im Moment schaffe ich es, Zeilen nach dem n-ten Komma umzubrechen, aber das ist nicht effizient, da in vielen Fällen viele Leerzeichen nach, sagen wir, dem 3. Komma verbleiben. Deshalb möchte ich, dass das Komma vor dem Zeilenumbruch so nah wie möglich am 80. Zeichen liegt.

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

Ich habe mir die Dokumentation zu „par“, „fold“ und „fmt“ ohne Erfolg angesehen. „fold“ kommt dem nahe, trennt die Zeilen aber durch Leerzeichen und nicht durch Kommas:

sed -i -r '/usage/{:a;N;/\.\.\./!ba;s/\n//g}' filename.txt
fold -s filename.txt | tee filename.txt

Antwort1

Verwendung von 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

Der awkCode mit Anmerkungen:

/^\\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

Antwort2

Eine einfache Variante, die perlden Slurp-Modus verwendet:

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

Das ergibt:

         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

verwandte Informationen