Wie kann ich eine einzelne Zeile mit begrenzten Elementen numerisch sortieren?

11

Ich habe eine Zeile (oder viele Zeilen) mit Zahlen, die durch ein beliebiges Zeichen begrenzt sind. Mit welchen UNIX-Tools kann ich die Elemente jeder Zeile numerisch sortieren, wobei das Trennzeichen beibehalten wird?

Beispiele beinhalten:

  • Liste der Zahlen; Eingabe : 10 50 23 42; sortiert:10 23 42 50
  • IP Adresse; Eingabe : 10.1.200.42; sortiert:1.10.42.200
  • CSV; Eingabe : 1,100,330,42; sortiert:1,42,100,330
  • pfeifenbegrenzt; Eingabe : 400|500|404; sortiert:400|404|500

Da das Trennzeichen beliebig ist, können Sie eine Antwort mit einem einstelligen Trennzeichen Ihrer Wahl bereitstellen (oder erweitern).

Jeff Schaller
quelle
8
du solltest es auf codegolf posten :)
ivanivan
1
Es gibt auch hier eine ähnliche Frage. Ich möchte den Link Alphabetisieren von Wörtern in Dateinamen mit sort
αғsнιη
Nur ein Hinweis, cutder mit seiner -dOption beliebige Trennzeichen unterstützt .
Oleg Lobachev
Bitte klären Sie, ob sich diese vier Beispiele für DSVs in derselben Datei befinden oder Beispiele aus vier verschiedenen Dateien sind.
Agc
2
Einige der anderen Kommentare sehen: Das Trennzeichen ist willkürlich, wird aber in der Eingabe konsistent verwendet. Nehmen Sie an, dass der Datenproduzent Informationen so enthält, dass er keine Kommas als Trennzeichen und in den Daten verwendet (zum Beispiel 4,325 comma 55 comma 42,430nicht und auch nicht 1.5 period 4.2).
Jeff Schaller

Antworten:

12

Sie können dies erreichen mit:

tr '.' '\n' <<<"$aline" | sort -n | paste -sd'.' -

Ersetzen Sie Punkte . durch Ihr Trennzeichen.
Fügen Sie -udem sortobigen Befehl hinzu, um die Duplikate zu entfernen.


oder mit gawk( GNU awk ) können wir viele Zeilen verarbeiten, während das Obige auch erweitert werden kann:

gawk -v SEP='*' '{ i=0; split($0, arr, SEP); 
    while ( ++i<=asort(arr) ){ printf("%s%s", i>1?SEP:"", arr[i]) }; 
        print "" 
}' infile

Ersetzen Sie *als Feldtrennzeichen SEP='*'durch Ihr Trennzeichen .


Hinweise:
Möglicherweise müssen Sie die -g, --general-numeric-sortOption sortanstelle von verwenden -n, --numeric-sort, um eine beliebige Klasse von Zahlen (Ganzzahl, Gleitkomma, Wissenschaft, Hexadezimal usw.) zu verarbeiten.

$ aline='2e-18,6.01e-17,1.4,-4,0xB000,0xB001,23,-3.e+11'
$ tr ',' '\n' <<<"$aline" |sort -g | paste -sd',' -
-3.e+11,-4,2e-18,6.01e-17,1.4,23,0xB000,0xB001

Wenn awkkeine Änderung erforderlich ist, werden diese weiterhin behandelt.

αғsнιη
quelle
10

Mit perlgibt es eine offensichtliche Version; Teilen Sie die Daten auf, sortieren Sie sie und verbinden Sie sie erneut.

Das Trennzeichen muss zweimal aufgeführt werden (einmal in splitund einmal in join)

zB für a ,

perl -lpi -e '$_=join(",",sort {$a <=> $b} split(/,/))'

So

echo 1,100,330,42 | perl -lpi -e '$_=join(",",sort {$a <=> $b} split(/,/))'
1,42,100,330

Da splites sich um eine Regex handelt, muss das Zeichen möglicherweise in Anführungszeichen gesetzt werden:

echo 10.1.200.42 | perl -lpi -e '$_=join(".",sort {$a <=> $b} split(/\./))'
1.10.42.200

Mit den Optionen -aund -Fkönnen Sie die Aufteilung entfernen. Mit der -pSchleife wie zuvor und setzen Sie die Ergebnisse auf $_, die automatisch gedruckt werden:

perl -F'/\./' -aple '$_=join(".", sort {$a <=> $b} @F)'
Stephen Harris
quelle
4
Sie können die -lOption anstelle von verwenden chomp. Dadurch wird auch die neue Zeile beim Drucken wieder hinzugefügt. Siehe auch -a(mit -F) für den Teilung.
Stéphane Chazelas
1
Mit -lund -Fist es noch schöner:perl -F'/\./' -le 'print join(".", sort {$a <=> $b} @F)'
Muru
@ StéphaneChazelas danke für die -lOption; Das hatte ich verpasst!
Stephen Harris
1
@muru Ich habe das -FFlag ursprünglich nicht verwendet, weil es nicht in allen Versionen richtig funktioniert (z. B. Ihre Zeile in CentOS 7 - Perl 5.16.3 - gibt eine leere Ausgabe zurück, obwohl es unter Debian 9 einwandfrei funktioniert). In Kombination -pergibt sich jedoch ein etwas kleineres Ergebnis, weshalb ich dies als Alternative zur Antwort hinzufügte. zeigt, wie -Fverwendet werden kann. Vielen Dank!
Stephen Harris
2
@ StephenHarris, weil neuere Versionen von Perl automatisch hinzufügen -aund -nOptionen, wann -Fund -nwann -averwendet wird ... also wechseln Sie einfach -lezu-lane
Sundeep
4

Mit Python und einer ähnlichen Idee wie in Stephen Harris 'Antwort :

python3 -c 'import sys; c = sys.argv[1]; sys.stdout.writelines(map(lambda x: c.join(sorted(x.strip().split(c), key=int)) + "\n", sys.stdin))' <delmiter>

Also so etwas wie:

$ cat foo
10.129.3.4
1.1.1.1
4.3.2.1
$ python3 -c 'import sys; c = sys.argv[1]; sys.stdout.writelines(map(lambda x: c.join(sorted(x.strip().split(c), key=int)) + "\n", sys.stdin))' . < foo
3.4.10.129
1.1.1.1
1.2.3.4

Leider ist die manuelle Ausführung der E / A weitaus weniger elegant als bei der Perl-Version.

muru
quelle
3

Schale

Das Laden einer höheren Sprache braucht Zeit.
Für einige Zeilen kann die Shell selbst eine Lösung sein.
Wir können den externen Befehl sortund den Befehl verwenden tr. Einer ist sehr effizient beim Sortieren von Zeilen und der andere konvertiert effektiv ein Trennzeichen in Zeilenumbrüche:

#!/bin/bash
shsort(){
           while IFS='' read -r line; do
               echo "$line" | tr "$1" '\n' |
               sort -n   | paste -sd "$1" -
           done <<<"$2"
    }

shsort ' '    '10 50 23 42'
shsort '.'    '10.1.200.42'
shsort ','    '1,100,330,42'
shsort '|'    '400|500|404'
shsort ','    '3 b,2       x,45    f,*,8jk'
shsort '.'    '10.128.33.6
128.17.71.3
44.32.63.1'

Dies muss nur wegen der Verwendung von Bash <<<. Wenn dies durch ein Here-Doc ersetzt wird, gilt die Lösung für posix.
Dies ist in der Lage zu sortieren Felder mit Tabulatoren, Leerzeichen oder der Schale glob Zeichen ( *, ?, [). Keine Zeilenumbrüche, da jede Zeile sortiert wird.

Wechseln Sie <<<"$2"zu <"$2", um Dateinamen zu verarbeiten, und nennen Sie es wie folgt:

shsort '.'    infile

Das Trennzeichen ist für die gesamte Datei gleich. Wenn dies eine Einschränkung ist, könnte sie verbessert werden.

Die Verarbeitung einer Datei mit nur 6000 Zeilen dauert jedoch 15 Sekunden. Die Shell ist wirklich nicht das beste Werkzeug, um Dateien zu verarbeiten.

Awk

Für mehr als ein paar Zeilen (mehr als ein paar Zehner) ist es besser, eine echte Programmiersprache zu verwenden. Eine awk-Lösung könnte sein:

#!/bin/bash
awksort(){
           gawk -v del="$1" '{
               split($0, fields, del)
               l=asort(fields)
               for(i=1;i<=l;i++){
                   printf( "%s%s" , (i==0)?"":del , fields[i] )
               }
               printf "\n"
           }' <"$2"
         }

awksort '.'    infile

Dies dauert nur 0,2 Sekunden für dieselbe 6000-Zeilen-Datei, die oben erwähnt wurde.

Verstehen Sie, dass die <"$2"for-Dateien wieder in <<<"$2"for-Zeilen innerhalb von Shell-Variablen geändert werden können.

Perl

Die schnellste Lösung ist Perl.

#!/bin/bash
perlsort(){  perl -lp -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' <<<"$2";   }

perlsort ' '    '10 50 23 42'
perlsort '.'    '10.1.200.42'
perlsort ','    '1,100,330,42'
perlsort '|'    '400|500|404'
perlsort ','    '3 b,2       x,45    f,*,8jk'
perlsort '.'    '10.128.33.6
128.17.71.3
44.32.63.1'

Wenn Sie eine Datei ändern möchten, ändern Sie <<<"$a"sie einfach "$a"und fügen Sie sie -izu Perl-Optionen hinzu, um die Datei-Edition "an Ort und Stelle" zu machen:

#!/bin/bash
perlsort(){  perl -lpi -e '$_=join("'"$1"'",sort {$a <=> $b} split(/['"$1"']/))' "$2"; }

perlsort '.' infile; exit
Isaac
quelle
2

Verwenden sedzum Sortieren von Oktetten einer IP-Adresse

sedverfügt nicht über eine integrierte in sortFunktion, aber wenn Sie Ihre Daten ausreichend in Bereich (zB mit IP - Adressen) eingeschränkt ist, können Sie einen sed - Skript , dass manuell implementiert eine einfache erzeugen Blasensortierung . Der grundlegende Mechanismus besteht darin, nach benachbarten Nummern zu suchen, die nicht in der richtigen Reihenfolge sind. Wenn die Nummern nicht in Ordnung sind, tauschen Sie sie aus.

Das sedSkript selbst enthält zwei Such- und Austauschbefehle für jedes Paar von Zahlen außerhalb der Reihenfolge: einen für die ersten beiden Oktettpaare (wodurch ein abschließendes Trennzeichen vorhanden sein muss, um das Ende des dritten Oktetts zu markieren) und a zweite für das dritte Oktettpaar (Ende mit EOL). Wenn Swaps auftreten, verzweigt das Programm an den Anfang des Skripts und sucht nach Zahlen, die nicht in der richtigen Reihenfolge sind. Andernfalls wird es beendet.

Das generierte Skript ist teilweise:

$ head -n 3 generated.sed
:top
s/255\.254\./254.255./g; s/255\.254$/254.255/
s/255\.253\./253.255./g; s/255\.253$/253.255/

# ... middle of the script omitted ...

$ tail -n 4 generated.sed
s/2\.1\./1.2./g; s/2\.1$/1.2/
s/2\.0\./0.2./g; s/2\.0$/0.2/
s/1\.0\./0.1./g; s/1\.0$/0.1/
ttop

Bei diesem Ansatz wird der Punkt als Trennzeichen fest codiert, das maskiert werden muss, da er sonst für die Syntax regulärer Ausdrücke "speziell" wäre (wobei jedes Zeichen zulässig ist).

Um ein solches sed-Skript zu generieren, führt diese Schleife Folgendes aus:

#!/bin/bash

echo ':top'

for (( n = 255; n >= 0; n-- )); do
  for (( m = n - 1; m >= 0; m-- )); do
    printf '%s; %s\n' "s/$n\\.$m\\./$m.$n./g" "s/$n\\.$m\$/$m.$n/"
  done
done

echo 'ttop'

Leiten Sie beispielsweise die Ausgabe dieses Skripts in eine andere Datei um sort-ips.sed.

Ein Probelauf könnte dann so aussehen:

ip=$((RANDOM % 256)).$((RANDOM % 256)).$((RANDOM % 256)).$((RANDOM % 256))
printf '%s\n' "$ip" | sed -f sort-ips.sed

Die folgende Variante der Erzeugungs Skript verwendet die Wortgrenzmarkierungen \<und \>auf die Notwendigkeit des zweiten Wechsel loszuwerden. Dadurch wird auch die Größe des generierten Skripts von 1,3 MB auf knapp 900 KB reduziert und die Laufzeit des Skripts erheblich reduziert sed(auf etwa 50% bis 75% des Originals, je nachdem, welche sedImplementierung verwendet wird):

#!/bin/bash

echo ':top'

for (( n = 255; n >= 0; --n )); do
  for (( m = n - 1; m >= 0; --m )); do
      printf '%s\n' "s/\\<$n\\>\\.\\<$m\\>/$m.$n/g"
  done
done

echo 'ttop'
Jeff Schaller
quelle
1
Eine interessante Idee, aber sie scheint die Dinge ein wenig zu komplizieren.
Matt
1
@ Matt Es ist irgendwie der Punkt. Alles zu sortieren sedist lächerlich, weshalb es eine interessante Herausforderung ist.
Kusalananda
2

Hier eine Bash, die den Begrenzer selbst errät:

#!/bin/bash

delimiter="${1//[[:digit:]]/}"
if echo $delimiter | grep -q "^\(.\)\1\+$"
then
  delimiter="${delimiter:0:1}"
  if [[ -z $(echo $1 | grep "^\([0-9]\+"$delimiter"\([0-9]\+\)*\)\+$") ]]
  then
    echo "You seem to have empty fields between the delimiters."
    exit 1
  fi
  if [[ './\' == *$delimiter* ]]
  then
    n=$( echo $1 | sed "s/\\"$delimiter"/\\n/g" | sort -n | tr '\n' ' ' | sed -e "s/\\s/\\"$delimiter"/g")
  else
    n=$( echo $1 | sed "s/"$delimiter"/\\n/g" | sort -n | tr '\n' ' ' | sed -e "s/\\s/"$delimiter"/g")
  fi
  echo ${n%$delimiter}
  exit 0
else
  echo "The string does not consist of digits separated by one unique delimiter."
  exit 1
fi

Es ist vielleicht nicht sehr effizient oder sauber, aber es funktioniert.

Verwenden Sie wie bash my_script.sh "00/00/18/29838/2".

Gibt einen Fehler zurück, wenn dasselbe Trennzeichen nicht konsistent verwendet wird oder wenn zwei oder mehr Trennzeichen aufeinander folgen.

Wenn das verwendete Trennzeichen ein Sonderzeichen ist, wird es maskiert (andernfalls wird sedein Fehler zurückgegeben).

jkd
quelle
Das inspirierte dies .
Agc
2

Diese Antwort basiert auf einem Missverständnis des Q., aber in einigen Fällen ist sie trotzdem richtig. Wenn es sich bei der Eingabe ausschließlich um natürliche Zahlen handelt und nur ein Trennzeichen pro Zeile vorhanden ist (wie bei den Beispieldaten im Q.), funktioniert dies ordnungsgemäß. Es werden auch Dateien mit Zeilen verarbeitet, die jeweils ein eigenes Trennzeichen haben. Dies ist etwas mehr als gewünscht.

Diese Shell-Funktion stammt readaus der Standardeingabe, verwendet die POSIX-Parametersubstitution , um das spezifische Trennzeichen in jeder Zeile zu finden (gespeichert in $d), und ersetzt die Daten dieser Zeile trdurch $deine neue Zeile \nund sorts und stellt dann die ursprünglichen Trennzeichen jeder Zeile wieder her:

sdn() { while read x; do
            d="${x#${x%%[^0-9]*}}"   d="${d%%[0-9]*}"
            x=$(echo -n "$x" | tr "$d" '\n' | sort -g | tr '\n' "$d")
            echo ${x%?}
        done ; }

Auf die im OP angegebenen Daten angewendet :

printf "%s\n" "10 50 23 42" "10.1.200.42" "1,100,330,42" "400|500|404" | sdn

Ausgabe:

10 23 42 50
1.10.42.200
1,42,100,330
400|404|500
agc
quelle
Das Trennzeichen in einer Zeile ist konsistent. Allgemeine Lösungen, mit denen der Benutzer das Trennzeichen deklarieren kann, sind fantastisch. Bei den Antworten kann jedoch jedes für sie sinnvolle Trennzeichen vorausgesetzt werden (einzelnes Zeichen und nicht in den numerischen Daten selbst vorhanden).
Jeff Schaller
2

Für beliebige Trennzeichen:

perl -lne '
  @list = /\D+|\d+/g;
  @sorted = sort {$a <=> $b} grep /\d/, @list;
  for (@list) {$_ = shift@sorted if /\d/};
  print @list'

Bei einer Eingabe wie:

5,4,2,3
6|5,2|4
There are 10 numbers in those 3 lines

Es gibt:

2,3,4,5
2|4,5|6
There are 3 numbers in those 10 lines
Stéphane Chazelas
quelle
0

Dies sollte alle nicht-stelligen (0-9) Trennzeichen behandeln. Beispiel:

x='1!4!3!5!2'; delim=$(echo "$x" | tr -d 0-9 | cut -b1); echo "$x" | tr "$delim" '\n' | sort -g | tr '\n' "$delim" | sed "s/$delim$/\n/"

Ausgabe:

1!2!3!4!5
Alexander
quelle
0

Mit perl:

$ # -a to auto-split on whitespace, results in @F array
$ echo 'foo baz v22 aimed' | perl -lane 'print join " ", sort @F'
aimed baz foo v22
$ # {$a <=> $b} for numeric comparison, {$b <=> $a} will give descending order
$ echo '1,100,330,42' | perl -F, -lane 'print join ",", sort {$a <=> $b} @F'
1,42,100,330

Mit ruby, was etwas ähnlich ist wieperl

$ # -a to auto-split on whitespace, results in $F array
$ # $F is sorted and then joined using the given string
$ echo 'foo baz v22 aimed' | ruby -lane 'print $F.sort * " "'
aimed baz foo v22

$ # (&:to_i) to convert string to integer
$ echo '1,100,330,42' | ruby -F, -lane 'print $F.sort_by(&:to_i) * ","'
1,42,100,330

$ echo '10.1.200.42' | ruby -F'\.' -lane 'print $F.sort_by(&:to_i) * "."'
1.10.42.200


Benutzerdefinierter Befehl und Übergabe nur der Trennzeichenfolge (kein regulärer Ausdruck). Funktioniert, wenn die Eingabe auch schwebende Daten enthält

$ # by default join uses value of $,
$ sort_line(){ ruby -lne '$,=ENV["d"]; print $_.split($,).sort_by(&:to_f).join' ; }

$ s='103,14.5,30,24'
$ echo "$s" | d=',' sort_line
14.5,24,30,103
$ s='10.1.200.42'
$ echo "$s" | d='.' sort_line
1.10.42.200

$ # for file input
$ echo '123--87--23' > ip.txt
$ echo '3--12--435--8' >> ip.txt
$ d='--' sort_line <ip.txt
23--87--123
3--8--12--435


Benutzerdefinierter Befehl für perl

$ sort_line(){ perl -lne '$d=$ENV{d}; print join $d, sort {$a <=> $b} split /\Q$d/' ; }
$ s='123^[]$87^[]$23'
$ echo "$s" | d='^[]$' sort_line 
23^[]$87^[]$123


Weiterführende Literatur - Ich hatte bereits diese praktische Liste von Perl / Ruby-Einzeilern

Sundeep
quelle
0

Das Folgende ist eine Variation von Jeffs Antwort in dem Sinne, dass sie a erzeugtsed Skript , das die Blasensortierung ausführt, aber ausreichend unterschiedlich ist, um eine eigene Antwort zu rechtfertigen.

Der Unterschied besteht darin, dass anstelle von O (n ^ 2) grundlegenden regulären Ausdrücken O (n) erweiterte reguläre Ausdrücke generiert werden. Das resultierende Skript wird ungefähr 15 KB groß sein. Die Laufzeit dessed Skripts beträgt Sekundenbruchteile (das Generieren des Skripts dauert etwas länger).

Es ist auf das Sortieren positiver Ganzzahlen beschränkt, die durch Punkte begrenzt sind, aber nicht auf die Größe der Ganzzahlen (nur erhöhen) 255 in der Hauptschleife) oder die Anzahl der Ganzzahlen beschränkt. Das Trennzeichen kann durch Ändern delim='.'des Codes geändert werden .

Es ist mir ein Rätsel, die regulären Ausdrücke richtig zu machen, also werde ich die Details für einen weiteren Tag beschreiben.

#!/bin/bash

# This function creates a extended regular expression
# that matches a positive number less than the given parameter.
lt_pattern() {
    local n="$1"  # Our number.
    local -a res  # Our result, an array of regular expressions that we
                  # later join into a string.

    for (( i = 1; i < ${#n}; ++i )); do
        d=$(( ${n: -i:1} - 1 )) # The i:th digit of the number, from right to left, minus one.

        if (( d >= 0 )); then
            res+=( "$( printf '%d[0-%d][0-9]{%d}' "${n:0:-i}" "$d" "$(( i - 1 ))" )" )
        fi
    done

    d=${n:0:1} # The first digit of the number.
    if (( d > 1 )); then
        res+=( "$( printf '[1-%d][0-9]{%d}' "$(( d - 1 ))" "$(( ${#n} - 1 ))" )" )
    fi

    if (( n > 9 )); then
        # The number is 10 or larger.
        res+=( "$( printf '[0-9]{1,%d}' "$(( ${#n} - 1 ))" )" )
    fi

    if (( n == 1 )); then
        # The number is 1. The only thing smaller is zero.
        res+=( 0 )
    fi

    # Join our res array of expressions into a '|'-delimited string.
    ( IFS='|'; printf '%s\n' "${res[*]}" )
}

echo ':top'

delim='.'

for (( n = 255; n > 0; --n )); do
    printf 's/\\<%d\\>\\%s\\<(%s)\\>/\\1%s%d/g\n' \
        "$n" "$delim" "$( lt_pattern "$n" )" "$delim" "$n"
done

echo 'ttop'

Das Skript sieht ungefähr so ​​aus:

$ bash generator.sh >script.sed
$ head -n 5 script.sed
:top
s/\<255\>\.\<(25[0-4][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.255/g
s/\<254\>\.\<(25[0-3][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.254/g
s/\<253\>\.\<(25[0-2][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.253/g
s/\<252\>\.\<(25[0-1][0-9]{0}|2[0-4][0-9]{1}|[1-1][0-9]{2}|[0-9]{1,2})\>/\1.252/g
$ tail -n 5 script.sed
s/\<4\>\.\<([1-3][0-9]{0})\>/\1.4/g
s/\<3\>\.\<([1-2][0-9]{0})\>/\1.3/g
s/\<2\>\.\<([1-1][0-9]{0})\>/\1.2/g
s/\<1\>\.\<(0)\>/\1.1/g
ttop

Die Idee hinter den generierten regulären Ausdrücken besteht darin, Musterübereinstimmungen für Zahlen vorzunehmen, die kleiner als jede Ganzzahl sind. Diese beiden Nummern wären nicht in der richtigen Reihenfolge und werden daher getauscht. Die regulären Ausdrücke sind in mehrere ODER-Optionen gruppiert. Achten Sie genau auf die Bereiche, die an jeden Artikel angehängt sind, manchmal auch. Dies {0}bedeutet, dass der unmittelbar vorherige Artikel bei der Suche weggelassen werden soll. Die Regex-Optionen von links nach rechts stimmen mit Zahlen überein, die kleiner als die angegebene Zahl sind, und zwar durch:

  • die einen Platz
  • die Zehnerstelle
  • die Hunderte Platz
  • (Fortsetzung nach Bedarf für größere Stückzahlen)
  • oder indem sie kleiner sind (Anzahl der Stellen)

Um ein Beispiel zu formulieren, nehmen Sie 101(mit zusätzlichen Leerzeichen für die Lesbarkeit):

s/ \<101\> \. \<(10[0-0][0-9]{0} | [0-9]{1,2})\> / \1.101 /g

Hier erlaubt der erste Wechsel die Zahlen 100 bis 100; Die zweite Abwechslung erlaubt 0 bis 99.

Ein weiteres Beispiel ist 154:

s/ \<154\> \. \<(15[0-3][0-9]{0} | 1[0-4][0-9]{1} | [0-9]{1,2})\> / \1.154 /g

Hier erlaubt die erste Option 150 bis 153; Die zweite erlaubt 100 bis 149 und die letzte erlaubt 0 bis 99.

Viermal in einer Schleife testen:

for test_run in {1..4}; do
    nums=$(( RANDOM%256 )).$(( RANDOM%256 )).$(( RANDOM%256 )).$(( RANDOM%256 ))
    printf 'nums=%s\n' "$nums"
    sed -E -f script.sed <<<"$nums"
done

Ausgabe:

nums=90.19.146.232
19.90.146.232
nums=8.226.70.154
8.70.154.226
nums=1.64.96.143
1.64.96.143
nums=67.6.203.56
6.56.67.203
Kusalananda
quelle
-2

Eingabe in mehrere Zeilen aufteilen

Mit trkönnen Sie die Eingabe mit einem beliebigen Trennzeichen in mehrere Zeilen aufteilen.

Diese Eingabe kann dann durchlaufen werden sort(unter Verwendung, -nwenn die Eingabe numerisch ist).

Wenn Sie das Trennzeichen in der Ausgabe beibehalten möchten, können Sie es trerneut verwenden, um das Trennzeichen wieder hinzuzufügen.

zB Leerzeichen als Trennzeichen verwenden

cat input.txt | tr " " "\n" | sort -n | tr "\n" " "

Eingabe: 1 2 4 1 4 32 18 3 Ausgabe:1 1 2 3 4 4 18 32

Matt
quelle
Sie können sicher von numerischen Elementen ausgehen, und ja: Das Trennzeichen sollte ersetzt werden.
Jeff Schaller