Kehren Sie die Reihenfolge der Zeichen in einer Zeichenfolge um

73

In der Zeichenfolge "12345" wird die Zeichenfolge "54321" ausgegeben. Am besten ohne Tools und Regex von Drittanbietern.

joar
quelle
unix.stackexchange.com/questions/121162/…
Ciro Santilli 6 冠状 病 六四.

Antworten:

29

Einfach:

var="12345"
copy=${var}

len=${#copy}
for((i=$len-1;i>=0;i--)); do rev="$rev${copy:$i:1}"; done

echo "var: $var, rev: $rev"

Ausgabe:

$ bash rev
var: 12345, rev: 54321

quelle
+1 Dies kann leicht erweitert werden, um beispielsweise ascii hexBytes umzukehren .
Kunstloser Lärm
Ich habe eine verbesserte Antwort hinzugefügt , da meine Bearbeitung nicht akzeptiert wurde (einschließlich einer POSIX-Lösung).
172

Ich weiß, dass Sie "ohne Tools von Drittanbietern" gesagt haben, aber manchmal ist ein Tool einfach zu offensichtlich das richtige und es ist standardmäßig auf den meisten Linux-Systemen installiert:

[madhatta@risby tmp]$ echo 12345|rev
54321
MadHatter
quelle
1
Aber nicht mit eingebetteten Distributionen wie OpenWRT: - /
bk138
1
Oder rev <<< 12345in Bash, Zsh und Ksh. (Nicht Dash noch Csh.)
Loxaxs
1
Ich höre dich, aber versuche es echo '\xff' |rev. Ich habe nie gesagt, dass echo -edas funktionieren würde, deshalb scheint es ein bisschen hart zu sein, mich über die Kohlen zu harken, wenn es nicht so ist.
MadHatter
Dies funktioniert nicht, wenn die Zeichenfolge eine neue Zeile enthält. revwirkt in jeder Zeile unabhängig und scheint keine Befehlszeilenoptionen zu haben, die dies ändern. Wie das Beispiel von @ Equidamoid zeigt (was übrigens nichts damit zu tun hat echo -e), wird außerdem davon ausgegangen , dass es sich bei der Zeichenfolge um eine ordnungsgemäß codierte Zeichenfolge handelt . Wenn Sie etwas um Bytes umkehren müssen (z. B. wenn Sie nicht mit Binärdaten anstelle von tatsächlichem Text arbeiten), funktioniert diese Lösung nicht. [Hinweis: Um die Formatierung zu korrigieren, habe ich diesen Kommentar gelöscht und erneut veröffentlicht. Entschuldigung für mögliche Phantombenachrichtigungen.]
greatBigDot
12

rev | tail -r(BSD) oder rev | tac(GNU) kehren auch Linien um:

$ rev <<< $'12\n34' | tail -r
43
21
$ rev <<< $'12\n34' | gtac
43
21

Wenn LC_CTYPE C ist, kehrt rev die Bytes der Multibyte-Zeichen um:

$ LC_CTYPE=C rev <<< あの
��め�
$ export LC_ALL=C; LC_ALL=en_US.UTF-8 rev <<< あの
のあ
Lri
quelle
+1 für die Erwähnung tac. Beachten Sie, dass tacdie Übergabe eines anderen Trennzeichens als die \nVerwendung der -sOption unterstützt wird.
Bart Kleijngeld
12

Angenommen, eine Variable 'var' hat den Wert '123'.

var="123"

Kehren Sie den String um und speichern Sie ihn in einer neuen Variablen 'rav':

rav=$(echo $var | rev)

Sie werden sehen, dass 'rav' mit echo den Wert '321' hat.

echo $rav
Nick
quelle
8

Eine Bash-Lösung, die sich gegenüber der @ osdyng-Antwort verbessert (meine Bearbeitung wurde nicht akzeptiert):

var="12345"     rev=""

for(( i=0 ; i<${#var} ; i++ )); do rev="${var:i:1}$rev"; done

echo "var: $var, rev: $rev"

Oder eine noch einfachere (Bash-) Schleife:

var=$1   len="${#var}"   i=0   rev=""

while (( i<len )); do rev="${var:i++:1}$rev"; done

echo "var: $var, rev: $rev"

Eine POSIX-Lösung:

var="12345"     rev=""    i=1

while  [ "$i" -le "${#var}" ]
do     rev="$(echo "$var" | awk -v i="$i" '{print(substr($0,i,1))}')$rev"
       : $(( i+=1 ))
done

echo "var: $var, rev: $rev"

Hinweis: Dies funktioniert mit Multi-Byte-Zeichenfolgen. Schnittlösungen funktionieren nur in ASCII-Zeichenfolgen (1 Byte).


quelle
Wenn Sie sowieso auf awk angewiesen sind, warum nicht einfach einmal und nicht in einer Schleife ausführen? awk '{for(i=length($0);i;i--)printf "%s",substr($0,i,1); print ""}'oder sogarawk '{for(i=length($0);i;i--)x=x substr($0,i,1); print x}'
Ghoti
6

Dies kehrt die Zeichenfolge "an Ort und Stelle" um:

a=12345
len=${#a}
for ((i=1;i<len;i++)); do a=$a${a: -i*2:1}; done; a=${a:len-1}
echo $a

oder die dritte Zeile könnte sein:

for ((i=0;i<len;i++)); do a=${a:i*2:1}$a; done; a=${a:0:len}

oder

for ((i=1;i<len;i++)); do a=${a:0:len-i-1}${a: -i:i+1}${a:len-i-1:1}; done
Bis auf weiteres angehalten.
quelle
6

Für diejenigen ohne rev (empfohlen) gibt es die folgende einfache awk- Lösung, die Felder in der Nullzeichenfolge aufteilt (jedes Zeichen ist ein separates Feld) und umgekehrt druckt:

awk -F '' '{ for(i=NF; i; i--) printf("%c", $i); print "" }'

Der obige awk- Code ist POSIX-kompatibel. Da eine kompatible awk- Implementierung garantiert auf jedem POSIX-kompatiblen Betriebssystem vorhanden ist, sollte die Lösung daher nicht als "Drittanbieter" betrachtet werden. Dieser Code ist wahrscheinlich prägnanter und verständlicher als eine reine POSIX sh (oder bash ) -Lösung.

(; Ich weiß nicht, ob Sie die Nullzeichenfolge für -F als regulären Ausdruck betrachten ...;)

Michael Zurück
quelle
5

Einige einfache Methoden zum Umkehren einer Zeichenfolge

echo '!!!esreveR si sihT' | grep -o . | tac | tr -d '\n' ; echo

echo '!!!esreveR si sihT' | fold -w 1 | tac | tr -d '\n' ; echo

In Hex-Werte konvertieren und dann umkehren

echo '!!!esreveR si sihT' | xxd -p | grep -o .. | tac | xxd -r -p ; echo

echo '!!!esreveR si sihT' | xxd -p | fold -w 2 | tac | xxd -r -p ; echo
David Heffernan
quelle
4

Wenn var=12345:

for((i=0;i<${#var};i++)); do rev="$rev${var:~i:1}"; done

c=$var; while [ "$c" ]; do rev=$rev${c#"${c%?}"}; c=${c%?}; done

echo "var: $var, rev: $rev"

Starte es:

$ rev
var: 12345, rev: 54321
Isaac
quelle
3

Dies kann natürlich verkürzt werden, aber es sollte einfach zu verstehen sein: Das Finale printfügt die neue Zeile hinzu.

echo 12345 | awk '{for (i = length($0); i > 0; i--) {printf("%s", substr($0, i, 1));} print "";}'
Nono
quelle
3

Niemand scheint eine sedLösung veröffentlicht zu haben , daher hier eine, die in Nicht-GNU-Sed funktioniert (daher würde ich sie nicht als "Drittanbieter" betrachten). Es werden zwar einzelne Zeichen mit dem regulären Ausdruck erfasst ., dies ist jedoch der einzige reguläre Ausdruck.

In zwei Schritten:

$ echo 123456 | sed $'s/./&\\\n/g' | sed -ne $'x;H;${x;s/\\n//g;p;}'
654321

Dies verwendet die Ersetzung des Bash-Formats, um Zeilenumbrüche in die Skripte aufzunehmen (da die Frage markiert ist ). Es funktioniert, indem zuerst die Eingabezeichenfolge in eine Zeile pro Zeichen getrennt wird und dann jedes Zeichen am Anfang des Haltepuffers eingefügt wird.

  • x vertauscht den Haltebereich und den Musterbereich und
  • H H hängt den (aktuellen) Musterraum an den Haltebereich an.

Also platzieren wir dieses Zeichen für jedes Zeichen in den Haltebereich und hängen dann den alten Haltebereich an ihn an, wodurch die Eingabe umgekehrt wird. Der letzte Befehl entfernt die Zeilenumbrüche, um die ursprüngliche Zeichenfolge zu rekonstruieren.

Dies sollte für jede einzelne Zeichenfolge funktionieren, verkettet jedoch mehrzeilige Eingaben zu einer einzelnen Ausgabezeichenfolge.

Ghoti
quelle
0

Hier ist eine weitere einfachere awkLösung:

awk 'BEGIN{FS=""} {for (i=NF; i>0; i--) s=s $i; print s}' <<< '123456'

654321
Anubhava
quelle
-1

Wort lesen

reve=`echo "$word" | awk '{for(i=length($0); i>0;i--) printf (substr($0,i,1));}'`
echo  "$reve"
Nikhil
quelle