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 awk
Code 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 perl
den 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