Mit welchen Befehlen wird eine durch Tabulatoren getrennte Textdatei eingezogen und jede Zeile auf 80 Zeichen gekürzt?

8

Ich habe mehrzeilige Textdateien mit (manchmal) tabulatorgetrennten Daten. Ich möchte die Datei ausgeben, damit ich einen Blick darauf werfen kann - also möchte ich nur die ersten 80 Zeichen jeder Zeile sehen (ich habe die Textdatei so gestaltet, dass das Wichtige in jeder Zeile an erster Stelle steht).

Ich hatte gedacht, ich könnte cat verwenden, um jede Zeile der Datei zu lesen und jede Zeile an den nächsten Befehl in einer Pipe zu senden:

cat tabfile | cut -c -80

Aber das schien kaputt zu sein. Ich habe versucht, herumzuspielen, und grep schien zu funktionieren - aber dann habe ich herausgefunden, dass dies nicht der Fall ist (nicht jede Zeile in der Datei hatte mehr als 80 Zeichen) - es scheint, dass Tabulatoren nach Schnitt als einzelne Zeichen gezählt werden.

Ich habe es versucht:

cat tabfile | tr \t \040 | cut -c -80

Auch wenn dies meine Daten ein wenig beschädigen würde, indem die Lesbarkeit des Leerraums beseitigt wird. Aber das hat nicht funktioniert. Weder tat:

cat tabfile | tr \011 \040 | cut -c -80

Vielleicht benutze ich tr falsch? Ich hatte zuvor Probleme mit tr, weil ich mehrere Leerzeichen entfernen wollte (anscheinend hat die Version von tr, auf die ich auf diesem Computer Zugriff habe, die Option -s, um mehrere Zeichen zusammenzudrücken - ich muss möglicherweise mehr damit spielen).

Ich bin mir sicher, wenn ich herumspielen würde, könnte ich Perl, Awk oder Sed oder etwas anderes verwenden, um dies zu tun.

Ich möchte jedoch eine Lösung, die (POSIX?) Reguläre Befehle verwendet, damit sie so portabel wie möglich ist. Wenn ich am Ende tr verwende, würde ich wahrscheinlich versuchen, Tabulatoren in Zeichen umzuwandeln, vielleicht eine Berechnung durchzuführen, die Berechnung zu kürzen und diese Zeichen dann wieder in Tabulatoren für die Ausgabe umzuwandeln.

Es muss keine einzelne Zeile sein / direkt in die Befehlszeile eingegeben werden - ein Skript ist in Ordnung.


Weitere Infos zu Tab-Dateien:

Ich benutze die Registerkarte, um Felder zu unterbrechen, weil ich eines Tages möglicherweise Daten in ein anderes Programm importieren möchte. Daher habe ich in der Regel nur eine Registerkarte zwischen den Inhalten. Ich verwende aber auch Registerkarten, um Dinge an vertikalen Spalten auszurichten und die Lesbarkeit beim Betrachten der Nur-Text-Datei zu verbessern. Das bedeutet, dass ich für einige Textteile das Ende des Inhalts mit Leerzeichen auffülle, bis ich an der Stelle bin, an der die Registerkarte das nächste Feld mit den darüber und darunter liegenden ausrichtet.

DarkTurquoise # 00CED1 Meere, Himmel, Ruderboote Natur
MediumSpringGreen # 00FA9A Nützlich für Bäume Magie  
Limette # 00FF00 Nur zur Verwendung bei Frühlingshühnern und Obst
user3082
quelle
Sie möchten also 80 Zeichen, die die Tabulatorbreite zählen? Sie können Tabulatoren durch eine entsprechende Anzahl von Leerzeichen ersetzen und dann Ausschneiden verwenden.
Muru
Annnnnd, wie kann ich (einfach) ein einzelnes Zeichen mit mehreren Zeichen erweitern? Oder, was noch wichtiger ist, mit einer variablen Anzahl von Zeichen (abhängig davon, wie viele andere Zeichen sich in der Zeile befinden), da ich die Registerkarte verwende, um Inhalte vertikal mit unterschiedlichen Informationsmengen vor / nach jeder Registerkarte auszurichten. Wie ich schon sagte, wenn ich perl / awk / sed lernen wollte, bin ich sicher, dass ich könnte, aber ich möchte etwas Einfaches
user3082
Sie könnten versuchen prvon coreutils: pr -1 -t -l200 -W80 file. Erhöhen / verringern Sie die Seitenlänge (Anzahl nach -l) nach Bedarf.
don_crissti
Don, dein Vorschlag (warum ist es keine Antwort?) Gibt mir eine nette Fehlermeldung. Aber der Mensch sagt "Pr-Print-Dateien" und untersucht das.
user3082
Don, mach das zu einer Antwort und lass es uns dort diskutieren. Ich habe etwas, das
Ihrem

Antworten:

9

Ich denke du suchst expandund / oder unexpand. Anscheinend versuchen Sie sicherzustellen, dass eine \tab-Breite als 8 Zeichen und nicht als einzelnes Zeichen zählt. foldwird das auch tun, aber es wird seine Eingabe in die nächste Zeile umbrechen, anstatt sie abzuschneiden. Ich denke du willst:

expand < input | cut -c -80

expandund unexpandsind beide POSIX angegeben :

  • Das expandDienstprogramm schreibt Dateien oder die Standardeingabe in die Standardausgabe, wobei \tab-Zeichen durch ein oder mehrere Leerzeichen ersetzt werden , die zum Auffüllen des nächsten Tabulators erforderlich sind. Alle Rücktastezeichen werden in die Ausgabe kopiert und bewirken, dass die Anzahl der Spaltenpositionen für Tabulatorberechnungen dekrementiert wird. Die Anzahl der Spaltenpositionen darf nicht unter Null dekrementiert werden.

Ziemlich einfach. Hier ist ein Blick darauf, was dies bewirkt:

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \\t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

Die untilSchleife oben erhält eine Reihe von Daten wie ...

1 1 2 2 3 3 ...

Es printfs dies mit der %*sArg- padding Flagge so für jeden der in dem Satz mittels printfTampon mit so viele Felder wie in der Nummer des Arguments sind. Jedem wird ein \tab-Zeichen angehängt .

Alle tees werden verwendet, um die Auswirkungen jedes Filters beim Anwenden anzuzeigen.

Und die Auswirkungen sind folgende:

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

Diese Reihen sind in zwei Sätzen wie ...

  1. Ausgabe von printf ...; echo
  2. Ausgabe von tr ...oderexpand
  3. Ausgabe von cut
  4. Ausgabe von wc

Die oberen vier Zeilen sind die Ergebnisse des trFilters, bei dem jeder \tab in ein einzelnes Leerzeichen konvertiert wird .

Und die unteren vier die Ergebnisse der expandKette.

mikeserv
quelle
1
Eigentlich ist es egal (zu viel), ob das \ t als 8 (5?) Oder eins gezählt wird, nur dass es nicht als eins gezählt und als 8 angezeigt wird.
user3082
+ @ anon3202 - macht vollkommen Sinn. Ich verstehe, was du meinst - (und die Länge des Tabstopps ist übrigens die Option cli) - ich habe es einfach nicht so gut gesagt, wie ich es hätte tun können. Hoffentlich verstehen Sie das Wesentliche - wie ich es nehme, haben Sie es vielleicht.
Mikeserv
Ich habe die Erklärung nicht ganz befolgt, aber das Herumspielen mit expand zeigt, dass expand definitiv das ist, wonach ich gesucht habe.
user3082
3

Da die Laschen als Begrenzung mehr für die Ausrichtung sind, könnte ein Weg zu benutzen , columnund dann cut:

column -s '\t' -t <some-file | cut -c -80

Es scheint columnnicht POSIX zu sein. Es ist Teil der BSD-Utils unter Ubuntu, daher gehe ich davon aus, dass es ziemlich plattformübergreifend ist.

muru
quelle
Auf columndiese Weise würde OP nicht einmal das manuelle Hinzufügen von Leerzeichen zum Ausrichten benötigen.
Beni Cherniavsky-Paskin
1

Dons Vorschlag in den Kommentaren war ein guter Anfang.

Dies ist, was ich brauchte, damit es (meistens) funktioniert:

pr +1 -1 -t -m -l1000 -w 80 tabfile

Das -mwurde benötigt, damit das -wFlag für eine einzelne Spalte wirksam wird. Die Manpage könnte neu geschrieben werden, um dies anzuzeigen.

Beim Versuch einer Problemumgehung stellte ich fest, dass Zeichen prausgegeben werden \t, sodass das Zuführen der Ergebnisse zu cutdemselben Problem führte.

-1 (die Spaltenflagge) sagt speziell in der Manpage:

Diese Option sollte nicht mit -m verwendet werden.

Ohne diese Option werden prLinien jedoch wohl oder übel abgeschnitten, und zwar viel kürzer als die angegebene Länge.

prFügt auch ein Leerzeichen vor (oder nach?) jedem Wort in ein Feld ein (dh jeder Ort, an dem ich ein einzelnes Leerzeichen habe, hat nach der Verarbeitung zwei). Wenn zu viele Wörter vorhanden sind, ignorieren die eingefügten Leerzeichen die -wEinschränkung (Erstellen eines Umlaufs). Aber seltsamerweise bleiben ansonsten nicht durch Tabulatoren getrennte (dh durch Leerzeichen angeordnete) "Spalten" in einer Reihe.

user3082
quelle
0

Verwenden von awk:

awk '{ $0 = substr($0, 1, 80) }1' file

Basierend auf Chris Downs Antwort hier .

Jasonwryan
quelle
Beißt es auf die \ t's - Aber dieser Link sieht vielversprechend aus
user3082
0

Ein Dienstprogramm, das sich wirklich der Anzeigebreite bewusst sein sollte, ist fold: Leider scheint es keine Option zum Verwerfen statt zum Umbrechen zu geben. Obwohl es wahrscheinlich schrecklich ineffizient ist, könnten Sie so etwas tun

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file
Steeldriver
quelle