So sortieren Sie nach Zeilen vom Terminal aus

7

Ich habe mir diese Frage angesehen und mich gefragt, ob das Folgende vom Terminal aus möglich ist. Ich habe es in Python gemacht, wollte nur sehen, ob es über Terminal, Bash-Scripting oder was auch immer gemacht werden kann.

Angenommen, ich habe eine Datei, die so aussieht:

2,4,5,14,9
40,3,5,10,1

könnte es so sortiert werden, nach Zeilen (Zeilen)

2,4,5,9,14
1,3,5,10,40

oder ist es zu kompliziert? Ich habe es mit Python gemacht, ich möchte nur wissen, ob es möglich ist, damit ich das nächste Mal Python nicht benutze. Was ich getan habe, ist Listen zu erstellen und sie zu sortieren.

Lynob
quelle
Ich habe es hier gestellt, weil ich die andere Frage gesehen habe. Wenn es hier nicht gestellt werden sollte, können Sie es
gerne
5
Ich habe das fehlende Komma zwischen 5und 14in Ihrem Eingabebeispiel hinzugefügt . Aufgrund Ihrer Ausgabe gehe ich davon aus, dass dies ein Tippfehler war. Bitte klären Sie, ob dies nicht der Fall war.
Terdon

Antworten:

5

Hier ist ein weiterer Perl-Ansatz:

perl -F, -lane 'print join ",",sort {$a<=>$b} @F' file.txt

Und noch eine Shell / Coreutils (obwohl ich persönlich die exzellente Antwort von Steeldriver bevorzuge, die dieselbe Idee verwendet):

while read line; do 
    tr , $'\n' < <(printf -- "%s" "$line") | sort -g | tr $'\n' , | sed 's/,$/\n/';
done < file.txt
Terdon
quelle
1
Gute Lösung, ich stimme sofort ab
Sylvain Pineau
Wie es dir gehört und wie ich :)
Terdon
Ich hasse es, wenn ich zu viele gute Antworten erhalte :) und wenn Sie zufällig eine auswählen müssen, ist es, als würde ich mich fragen: "Was mag ich mehr, Schokoriegel oder Eis?"
Lynob
7

Dies sollte ungefähr das tun, wonach Sie suchen. Es liest eine Datei (test.txt) und erstellt eine Ausgabedatei (sorted.txt) mit den sortierten Zeilen in der Reihenfolge, in der sie in der Originaldatei erscheinen.

while read line; do j=$(echo "$line" | sed -e 's/,/\n/g' | sort -n); echo "$j" 
    | sed -e 's/ /,/g' >> sorted.txt; done < test.txt
jkt123
quelle
Hast du das Leerzeichen in der ersten Zeile notiert 2,4,5 14,9?
Avinash Raj
schlechte Verwendung von Katze! Um auf jeder Linie zu operieren, tun Siewhile read line; do ...; done < test.txt
Fredrik Pihl
@FredrikPhil: Danke. Ich habe meine Antwort bearbeitet.
jkt123
4

Die einzige wirkliche Schwierigkeit bei der Ausführung von Befehlszeilenskripten besteht darin, dass die verfügbare sortFunktion erwartet, dass Zeilen innerhalb einer Datei und nicht Felder innerhalb einer Zeile sortiert werden . Um dies zu umgehen, können Sie die Feldtrennzeichen vor der sortFunktion zeilenweise durch Zeilenumbrüche ersetzen und die Zeilenumbrüche nach dem Sortieren in jeder Zeile erneut durch Trennzeichen ersetzen.

Es gibt eine Reihe von verfügbaren Textverarbeitungs Dienstprogramme , die Sie würde es ermöglichen , das zu tun (einschließlich sed, awkoder auch die einfachen tr) aber die Bash - Shell selbst heutzutage viel zu tun. Angenommen, Sie wollten, dass die Eingabe durch Kommas getrennt wird (in Ihrem Beispiel haben Sie eine Mischung aus Kommas und Leerzeichen), können Sie Folgendes tun:

while read line; do 
  sorted=$(sort -g -- <<< "${line//,/$'\n'}")
  printf -- "${sorted//$'\n'/,}\n"
done < file

Wenn Sie tun müssen , um Griffraum - Trennzeichen in der Eingabe, dann kann man sich als Teil einer Zeichenliste hinzufügen [, ]zur Eingabe Teilzeichenfolge Ersatz:

while read line; do 
  sorted=$(sort -g -- <<< "${line//[, ]/$'\n'}")
  printf -- "${sorted//$'\n'/,}\n"
done < file

(Beachten Sie, dass die Ausgabe jedoch streng durch Kommas getrennt bleibt).

Steeldriver
quelle
4

Hier kommt eine awkLösung,

while read -r line; do (echo $line | awk '{ n=split($1,a,","); asort(a); for(i=0;i<=n;i++) { print a[i];}}') | xargs | sed -e 's/ /,/g'; done < text.txt

Erläuterung:

  • awk '{ n=split($1,a,","); asort(a); for(i=0;i<=n;i++) { print a[i];}}'

    awk Teilt das Feld 1 nach dem Trennzeichen ,und speichert jeden Wert im Array. aSchließlich wird die oberste Position in der Variablen gespeichert n. Die nächste asort(a)Funktion sortiert die Array-Werte. Anschließend druckt die for-Schleife im Befehl awk die sortierten Werte im Format Datensatz für Datensatz.

  • xargs | sed -e 's/ /,/g'

    xargs kombiniert alle Zeilen zu einer einzigen Zeile.

  • sed -e 's/ /,/g'

    Es ersetzt die Leerzeichen durch Kommas ,

  • while read -r line;

    Alle oben genannten awk, xargs, sedsind Funktionen done Zeile für Zeile mit Hilfe der whileSchleife.

Avinash Raj
quelle
3

python -c "your code here" input.txt

Oder wenn Ihr Programm mehrere Zeilen hat und eval()zu langsam ist:

python yourprogram.py input.txt

Dieser Oneliner funktioniert:

python -c "for l in open('input.txt'):print(','.join(sorted(l.strip().split(','), key=int)))"
Cees Timmerman
quelle
Das OP sucht nicht nach einer Python-basierten Lösung.
Jobin
Ja, das ist er: "Ich möchte nur sehen, ob dies über Terminal, Bash-Scripting oder was auch immer möglich ist ."
Cees Timmerman
Lol, du hast es dann geschafft!
Jobin
3

Mit tr und sed

Ähnlich wie jkt123 :

while read i; do tr , \\n <<< $i | sort -n | tr \\n , | sed 's/,$//'; done

Es iteriert über die Zeilen und ersetzt für jede Zeile Kommas durch Zeilenumbrüche, sortiert die resultierenden Zeilen numerisch und wandelt Zeilenumbrüche wieder in Kommas um. Das Hauptproblem ist, dass dies das gesamte Ergebnis mit einem Komma und nicht mit einer neuen Zeile beendet, die von diesem letzten Sed angesprochen wird. Es entfernt das letzte Komma und fügt seiner Ausgabe implizit eine neue Zeile hinzu.

Verwenden von Bash-Arrays

Hier ist ein anderer Ansatz, um dieses Problem „Mit Kommas verbinden“ zu lösen:

while read i; do j=( $(tr , \\n <<< $i | sort -n) ); ( IFS=,; echo "${j[*]}"; ); done

Oder mit Zeilenumbrüchen geschrieben:

while read i
do
   j=( $(tr , \\n <<< $i | sort -n) )
   ( IFS=,; echo "${j[*]}"; )
done

Es verwendet ein Bash-Array, um das Ergebnis der sortierten Zeile zu speichern, und verwendet die Art und Weise, wie Bash Arrays mithilfe der IFSspeziellen Variablen in Zeichenfolgenliterale erweitert .

MvG
quelle
2

Sie können dies einfach mit Perl tun

Betrachten Sie, Sie haben Datei text.txt

cat text.txt

1,5,7,8,3,6
10,34,67,1,2,0,5

Der folgende Perl-Code sortiert nun die Zeilen text.txt

 perl -i -e 'while(<>){chomp; my @sorted = sort { $a <=> $b } split(",", $_); print join (",", @sorted); print "\n"}' text.txt

Nach dem Sortieren

cat text.txt

1,3,5,6,7,8
0,1,2,5,10,34,67
Stormvirux
quelle
2
Sie könnten dies mit erheblich verkürzen perl -i -lne 'print join (",", sort {$a <=> $b} split(",", $_));' text.txt. Das -nFlag ist dasselbe wie while(<>){}und -lfügt \njedem Druckaufruf ein hinzu und aktiviert auch implizit chomp().
Terdon
2

Die kürzeste Lösung mit einem Perl-Oneliner:

perl -ne 'print join(",", sort { $a <=> $b } split(/,|\n/))."\n"' text.txt
Sylvain Pineau
quelle
Heh, ich hatte meine Antwort für eine Weile offen gelassen und dies nicht gesehen, aber nicht die kürzeste: P
terdon
1
Je m'incline ;-)
Sylvain Pineau
1

Ich brauchte diese Funktionalität auch und fand eine Lösung wie folgt (vorausgesetzt, die Daten befinden sich in der Testdatei):

cat test | while read line; do echo $(echo $line | datamash -t',' transpose |sort -g| datamash -t',' transpose); done
Eissa N.
quelle