Antworten:
Mit der Kombination von tr
+ tac
+paste
$ tr '.' $'\n' <<< 'arg1.arg2.arg3.arg4.arg5' | tac | paste -s -d '.'
arg5.arg4.arg3.arg2.arg1
Wenn Sie immer noch Bash bevorzugen, können Sie auf diese Weise tun,
IFS=. read -ra line <<< "arg1.arg2.arg3.arg4."
let x=${#line[@]}-1;
while [ "$x" -ge 0 ]; do
echo -n "${line[$x]}.";
let x--;
done
Verwenden perl
,
$ echo 'arg1.arg2.arg3.arg4.arg5' | perl -lne 'print join ".", reverse split/\./;'
arg5.arg4.arg3.arg2.arg1
Wenn es Ihnen nichts ausmacht python
:
".".join(s.split(".")[::-1])
Beispiel:
$ python3 -c 's="arg1.arg2.arg3.arg4.arg5"; print(".".join(s.split(".")[::-1]))'
arg5.arg4.arg3.arg2.arg1
s.split(".")
generiert eine Liste mit .
getrennten Teilzeichenfolgen, [::-1]
kehrt die Liste um und ".".join()
verbindet die Komponenten der umgekehrten Liste mit .
.Sie können dies mit einem einzigen sed
Aufruf tun :
sed -E 'H;g;:t;s/(.*)(\n)(.*)(\.)(.*)/\1\4\5\2\3/;tt;s/\.(.*)\n/\1./'
Dies verwendet den Haltepuffer, um eine führende neue Zeile im Musterraum zu erhalten, und verwendet ihn, um Permutationen durchzuführen, bis auf die neue Zeile kein Punkt mehr folgt. An diesem Punkt wird der führende Punkt aus dem Musterraum entfernt und die neue Zeile durch einen Punkt ersetzt.
Mit BRE und einem etwas anderen Regex:
sed 'H
g
:t
s/\(.*\)\(\n\)\(.*\)\(\.\)\(.*\)/\1\4\5\2\3/
tt
s/\(\.\)\(.*\)\n/\2\1/'
Wenn die Eingabe aus mehr als einer Zeile besteht und Sie die Reihenfolge in jeder Zeile umkehren möchten:
sed -E 'G;:t;s/(.*)(\.)(.*)(\n)(.*)/\1\4\5\2\3/;tt;s/(.*)\n(\.)(.*)/\3\2\1/'
Mit zsh
:
$ string=arg1.arg2.arg3.arg4.arg5
$ printf '%s\n' ${(j:.:)${(Oas:.:)string}}
arg5.arg4.arg3.arg2.arg1
So bewahren Sie leere Elemente auf:
$ string=arg1.arg2.arg3.arg4..arg5.
$ printf '%s\n' ${(j:.:)"${(@Oas:.:)string}"}
.arg5..arg4.arg3.arg2.arg1
s:.:
: aufgeteilt auf .
Oa
: Sort Array in umgekehrter ein rray indice o rderj:.:
: mach mit .
.@
: do- "$@"
like-Erweiterung in doppelten Anführungszeichen, damit die Erweiterung nicht entleert wird.Das POSIX (oder bash
) Äquivalent könnte etwa so lauten:
string=arg1.arg2.arg3.arg4..arg5.
IFS=.; set -f
set -- $string$IFS # split string into "$@" array
unset pass
for i do # reverse "$@" array
set -- "$i" ${pass+"$@"}
pass=1
done
printf '%s\n' "$*" # "$*" to join the array elements with the first
# character of $IFS
(Beachten Sie, dass zsh
(in der sh
Emulation) yash
und einige pdksh
-basierte Shells in dieser Hinsicht keine POSIX-Shells sind, da sie $IFS
als Feldtrennzeichen anstelle eines Feldtrennzeichens behandelt werden. )
Wo es sich von einigen anderen hier angegebenen Lösungen unterscheidet, ist, dass es das Newline-Zeichen (und im Falle des zsh
NUL- Zeichens auch nicht) nicht speziell behandelt, das heißt, es $'ab.cd\nef.gh'
würde umgekehrt werden $'gh.cd\nef.ab'
, nicht $'cd.ab\ngh.ef'
oder $'gh.ef.cd.ab'
.
IFS="."; set -f; set -- $string$IFS; for i; do rev="$i$IFS$rev"; done; printf '%s\n' "${rev%$IFS}"
?
for i; do
davon, dass es sich (noch) nicht um POSIX handelt, selbst wenn es von allen mir bekannten POSIX-Shells unterstützt wird). Es ist nur so, dass diese Lösung eine direkte Übersetzung der zsh
einen Lösung ist (aufgeteilt in Array-, Reverse-Array- und Join-Array-Elemente), aber nur mit POSIX-Operatoren. (Ich habe die Einstellung auf geändert string=$string$IFS; set -- $string
, set -- $string$IFS
da dies über alle Shells hinweg konsistent zu funktionieren scheint, danke).
Ich sehe, Rahul hat (unter anderem) bereits eine native Bash-Lösung veröffentlicht, die eine kürzere Version der ersten ist, die ich mir ausgedacht habe:
function reversedots1() (
IFS=. read -a array <<<"$1"
new=${array[-1]}
for((i=${#array[*]} - 2; i >= 0; i--))
do
new=${new}.${array[i]}
done
printf '%s\n' "$new"
)
Aber ich konnte nicht damit aufhören und hatte das Bedürfnis, eine rekursive bash-zentrierte Lösung zu schreiben:
function reversedots2() {
if [[ $1 =~ ^([^.]*)\.(.*)$ ]]
then
printf %s $(reversedots2 "${BASH_REMATCH[2]}") . "${BASH_REMATCH[1]}"
else
printf %s "$1"
fi
}
Ich habe keine awk
Antwort gefunden. Hier ist eine:
echo 'arg1.arg2.arg3' | awk -F. '{for (i=NF; i>0; --i) printf "%s%s", (i<NF ? "." : ""), $i; printf "\n"}'