Ich habe zwei Textdateien. Der erste hat Inhalt:
Languages
Recursively enumerable
Regular
während der zweite Inhalt hat:
Minimal automaton
Turing machine
Finite
Ich möchte sie spaltenweise in einer Datei zusammenfassen. Also habe ich es versucht paste 1 2
und seine Ausgabe ist:
Languages Minimal automaton
Recursively enumerable Turing machine
Regular Finite
Ich möchte jedoch, dass die Spalten wie z
Languages Minimal automaton
Recursively enumerable Turing machine
Regular Finite
Ich habe mich gefragt, ob es möglich wäre, dies ohne manuelle Bearbeitung zu erreichen.
Hinzugefügt:
Hier ist ein anderes Beispiel, in dem Bruce es fast nagelt, außer einer leichten Fehlausrichtung, über die ich mich wundere, warum?
$ cat 1
Chomsky hierarchy
Type-0
—
$ cat 2
Grammars
Unrestricted
$ paste 1 2 | pr -t -e20
Chomsky hierarchy Grammars
Type-0 Unrestricted
— (no common name)
pr
undexpand
...columns
vermeidet dieses Problem.➀ unicode may render oddly
but the column count is ok
definitiv nicht nicht anzuwendenwc-paste-pr
undwc-paste-pr
Sie Zeige Unterschiede in der Spaltenanzahl. Die anderen sind in Ordnung.pr
das Multibyte Zeichen im aktuellen Gebietsschema (normalerweise UTF8).Antworten:
Sie müssen nur den
column
Befehl eingeben und ihn anweisen, Tabulatoren zum Trennen von Spalten zu verwendenUm die Kontroverse um "leere Zellen" anzugehen, brauchen wir nur die
-n
Optioncolumn
:Meine Spaltenmanpage zeigt an, dass
-n
es sich um eine "Debian GNU / Linux-Erweiterung" handelt. Mein Fedora-System weist kein Problem mit leeren Zellen auf: Es scheint von BSD abgeleitet zu sein und in der Manpage heißt es "Version 2.23 hat die Option -s so geändert, dass sie nicht gierig ist".quelle
column
natürlich; wie offensichtlich (imcolumn -s $'\t' -t
leere Zellen ignoriert werden , was dazu führt , dass alle nachfolgenden Zellen rechts davon (in dieser Zeile) nach links verschoben werden. dh als Ergebnis einer leeren Zeile in einer Datei, oder es ist kürzer ... :(Sie suchen nach dem praktischen Dandy-
pr
Befehl:Das "-e24" ist "Tabulatorstopps auf 24 Leerzeichen erweitern". Zum Glück wird
paste
ein Tabulator-Zeichen zwischen die Spalten gesetzt, damitpr
es erweitert werden kann. Ich habe 24 gewählt, indem ich die Zeichen in "Recursively enumerable" gezählt und 2 hinzugefügt habe.quelle
expand
Befehl direkt:paste file1 file2 | expand -t 24
?sed
, es gibt also einen Prozess, der nicht ausgeführt wird. Es verwendetpr
das ist ein alter Befehl, aus dem Jahr Unix SysV Tage, ich glaube, so ist es , als auf mehr Installationen bestehen könnteexpand
. Kurz gesagt, es ist nur alte Schule.Update : Hier ist ein viel einfacheres Skript (das am Ende der Frage) für die tabellarische Ausgabe. Übergeben
paste
Sie einfach den Dateinamen wiehtml
gewohnt ... Der Frame wird so erstellt, dass er angepasst werden kann. Es werden mehrere Leerzeichen beibehalten, und die Spaltenausrichtung wird beibehalten, wenn Unicode-Zeichen gefunden werden. Die Art und Weise, wie der Editor oder der Betrachter den Unicode rendert, ist jedoch eine ganz andere Sache ...---
Eine Übersicht über die in den Antworten vorgestellten Tools (bisher).
Ich habe sie mir ziemlich genau angesehen. Folgendes habe ich gefunden:
paste
# Dieses Tool ist allen bisher vorgestellten Antworten gemeinsam. # Es kann mehrere Dateien verarbeiten. daher mehrere Spalten ... Gut! # Es begrenzt jede Spalte mit einem Tabulator ... Gut. # Die Ausgabe ist nicht tabellarisch.Alle folgenden Tools entfernen dieses Trennzeichen! ... Schlecht, wenn Sie ein Trennzeichen benötigen.
column
# Es entfernt das Tab-Trennzeichen, so dass die Feldidentifizierung nur durch Spalten erfolgt, die es anscheinend recht gut handhabt. Ich habe nichts Falsches entdeckt ... # Abgesehen davon, dass es kein eindeutiges Trennzeichen gibt, funktioniert es einwandfrei!expand
# Hat nur eine Tabulatoreinstellung, ist also über 2 Spalten hinaus unvorhersehbarpr
# Verfügt nur über eine einzige Tabulatoreinstellung, so dass eine Überschreitung von 2 Spalten nicht vorhersehbar ist. # Die Ausrichtung der Spalten ist bei der Verarbeitung von Unicode nicht korrekt. Das Tabulator-Trennzeichen wird entfernt, sodass die Feldidentifizierung ausschließlich durch die Spaltenausrichtung erfolgtFür mich ist
column
es die offensichtlich beste Lösung als Einzeiler. Wenn Sie entweder das Trennzeichen oder eine ASCII-artige Tabellierung Ihrer Dateien wünschen, lesen Sie weiter, ansonstencolumns
ist es verdammt gut :) ...Hier ist ein Skript, das eine beliebige Anzahl von Dateien aufnimmt und eine tabellarische ASCII-Darstellung erstellt. (Beachten Sie, dass Unicode möglicherweise nicht die erwartete Breite aufweist, z. B. eg, das ein einzelnes Zeichen ist. Dies unterscheidet sich erheblich von der Spalte Zahlen sind falsch, wie es bei einigen der oben genannten Dienstprogramme der Fall ist.) ... Die unten gezeigte Ausgabe des Skripts stammt aus 4 Eingabedateien mit dem Namen F1 F2 F3 F4 ...
Hier ist meine ursprüngliche Antwort (anstelle des obigen Skripts etwas gekürzt)
Verwenden Sie
wc
, um die Spaltenbreite zu ermitteln undsed
das rechte Feld mit einem sichtbaren Zeichen zu versehen.
(nur für dieses Beispiel) ... und dannpaste
, um die beiden Spalten mit einem Tabulatorzeichen zu verbinden ...Wenn Sie die rechte Spalte ausfüllen möchten:
quelle
Du bist fast da.
paste
Fügt zwischen jede Spalte ein Tabulatorzeichen ein, sodass Sie nur die Tabulatoren erweitern müssen. (Ich gehe davon aus, dass Ihre Dateien keine Tabulatoren enthalten.) Sie müssen die Breite der linken Spalte bestimmen.wc -L
Zeigt mit (aktuell genug) GNU-Dienstprogrammen die Länge der längsten Zeile an. Machen Sie auf anderen Systemen einen ersten Durchgang mit awk. Dabei+1
handelt es sich um die Menge an Leerzeichen, die Sie zwischen den Spalten einfügen möchten.Wenn Sie über das BSD-Dienstprogramm für Spalten verfügen, können Sie damit die Spaltenbreite bestimmen und die Registerkarten auf einmal erweitern. (
␉
Ist ein wörtliches Tabulatorzeichen. Sie können es$'\t'
stattdessen unter bash / ksh / zsh und in jeder beliebigen Shell verwenden"$(printf '\t')"
.)quelle
wc
muss der Befehl sein:wc -L <left.txt
... weil, wenn Sie einen Dateinamen als Befehlszeilen spedified ist arg , seinen Namen auf stdout ausgegeben istDas ist mehrstufig, also nicht optimal, aber hier ist es.
1) Ermitteln Sie die Länge der längsten Zeile in
file1.txt
.In Ihrem Beispiel ist die längste Zeile 22.
2) Füllen Sie mit awk
file1.txt
jede Zeile mit weniger als 22 Zeichen bis zu 22 mit derprintf
Anweisung auf.Hinweis: Verwenden Sie für FS eine Zeichenfolge, die in nicht vorhanden ist
file1.txt
.3) Verwenden Sie die Paste wie zuvor.
Wenn Sie dies häufig tun, kann dies leicht in ein Skript umgewandelt werden.
quelle
while IFS= read -r line
, sonst wird die Shell Leerzeichen und Backslashes entstellen. Aber die Shell ist nicht das beste Werkzeug für diesen Job. Aktuelle Versionen von GNU Coreutils habenwc -L
(siehe freds Antwort), oder Sie können awk: verwendenawk 'n<length {n=length} END {print +n}'
.Ich kann die Antwort von Glenn Jackman nicht kommentieren, daher füge ich dies hinzu, um das Problem der leeren Zellen zu beheben, das Peter.O festgestellt hat. Durch Hinzufügen eines Nullzeichens vor jedem Tab werden die Trennzeichenfolgen eliminiert, die als einzelne Unterbrechungen behandelt werden, und das Problem wird behoben. (Ich habe ursprünglich Leerzeichen verwendet, aber durch die Verwendung des Nullzeichens wird der zusätzliche Abstand zwischen den Spalten eliminiert.)
Wenn das Nullzeichen aus verschiedenen Gründen Probleme verursacht, versuchen Sie Folgendes:
oder
Beide
sed
undcolumn
scheinen sich in der Implementierung in verschiedenen Versionen und Varianten von Unix / Linux zu unterscheiden, insbesondere BSD (und Mac OS X) gegenüber GNU / Linux.quelle
od -c
und sehe keine Null-Bytes. Dies ist auf Centos und Ubuntu.\0
funktionierte die Verwendung nicht alsnull
in sed,\x0
tat es aber. Die Spalte ergab jedoch einenline too long
Fehler. Am einfachsten scheint es, ein Leerzeichen zu verwenden und mit dem zusätzlichen Charakter zu leben.Aufbauend auf der Antwort von Bahamat : Dies kann vollständig in
awk
, nur einmaliges Lesen der Dateien und keine temporären Dateien erstellt werden. Um das Problem wie angegeben zu lösen, gehen Sie folgendermaßen vorWie bei vielen
awk
Skripten dieses Typs wird zuerst gelesenfile1
, wobei alle Daten imsave
Array gespeichert und gleichzeitig die maximale Zeilenlänge berechnet werden. Dann liestfile2
und druckt es die gespeicherten (file1
) Daten neben den aktuellen (file2
) Daten. Wennfile1
es länger ist alsfile2
(mehr Zeilen), drucken wir die letzten Zeilen vonfile1
(die, für die es keine entsprechende Zeile in der zweiten Spalte gibt).Zum
printf
Format:"%-nns"
Gibt eine Zeichenfolge aus, die linksbündig in einem Feld mit einernn
Breite von Zeichen angeordnet ist."%-*s", nn
tut das Gleiche - das*
sagt, es soll die Feldbreite vom nächsten Parameter übernehmen.maxlength+2
nn
+2
Das obige Skript funktioniert nur für zwei Dateien. Es kann trivial modifiziert werden, um drei Dateien oder vier Dateien usw. zu handhaben, aber dies wäre mühsam und wird als Übung belassen. Es stellt sich jedoch heraus, dass es nicht schwierig ist, es zu ändern, um eine beliebige Anzahl von Dateien zu verarbeiten:
Dies ist meinem ersten Skript sehr ähnlich, außer
max_length
in ein Array.max_FNR
in ein Array.save
zu einem zweidimensionalen Array.END
Blocks aus.quelle
paste
die beste Lösung ist. speziell Glenn Jackmanspaste file1 file2 | column -s $'\t' -t
. Aber ich dachte, es würde Spaß machen, denawk
Ansatz zu verbessern .