Réponses:
Utilisation d'une combinaison de tr+ tac+paste
$ tr '.' $'\n' <<< 'arg1.arg2.arg3.arg4.arg5' | tac | paste -s -d '.'
arg5.arg4.arg3.arg2.arg1Si vous préférez toujours bash, vous pouvez le faire de cette façon,
IFS=. read -ra line <<< "arg1.arg2.arg3.arg4."
let x=${#line[@]}-1;
while [ "$x" -ge 0 ]; do
echo -n "${line[$x]}.";
let x--;
doneUtilisation perl,
$ echo 'arg1.arg2.arg3.arg4.arg5' | perl -lne 'print join ".", reverse split/\./;'
arg5.arg4.arg3.arg2.arg1Si cela ne vous dérange pas un petit peu de python:
".".join(s.split(".")[::-1])
Exemple:
$ python3 -c 's="arg1.arg2.arg3.arg4.arg5"; print(".".join(s.split(".")[::-1]))'
arg5.arg4.arg3.arg2.arg1
s.split(".")génère une liste contenant .des sous-chaînes séparées, [::-1]inverse la liste et ".".join()joint les composants de la liste inversée avec ..Vous pouvez le faire avec une seule sedinvocation:
sed -E 'H;g;:t;s/(.*)(\n)(.*)(\.)(.*)/\1\4\5\2\3/;tt;s/\.(.*)\n/\1./'
cela utilise le tampon de maintien pour obtenir une nouvelle ligne de début dans l'espace de motif et l'utilise pour faire des permutations jusqu'à ce que la nouvelle ligne ne soit plus suivie par aucun point auquel point il supprime le point de tête de l'espace de motif et remplace la nouvelle ligne par un point.
Avec BRE et un regex légèrement différent:
sed 'H
g
:t
s/\(.*\)\(\n\)\(.*\)\(\.\)\(.*\)/\1\4\5\2\3/
tt
s/\(\.\)\(.*\)\n/\2\1/'
Si l'entrée se compose de plusieurs lignes et que vous souhaitez inverser l'ordre sur chaque ligne:
sed -E 'G;:t;s/(.*)(\.)(.*)(\n)(.*)/\1\4\5\2\3/;tt;s/(.*)\n(\.)(.*)/\3\2\1/'
Avec zsh:
$ string=arg1.arg2.arg3.arg4.arg5
$ printf '%s\n' ${(j:.:)${(Oas:.:)string}}
arg5.arg4.arg3.arg2.arg1
Pour conserver les éléments vides:
$ string=arg1.arg2.arg3.arg4..arg5.
$ printf '%s\n' ${(j:.:)"${(@Oas:.:)string}"}
.arg5..arg4.arg3.arg2.arg1
s:.:: divisé sur .Oa: Tableau de tri en sens inverse un rray indice o rderj:.:: rejoignez-nous ..@: "$@"extension à la manière des guillemets doubles pour que l'expansion ne soit pas supprimée à vide.L' bashéquivalent POSIX (ou ) pourrait ressembler à:
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
(notez que zsh(en shémulation), yashet certainspdksh shells basés sur ne sont pas POSIX à cet égard en ce qu'ils traitent $IFScomme un séparateur de champ au lieu d'un délimiteur de champ)
Là où il diffère de certaines des autres solutions données ici, c'est qu'il ne traite pas zshspécialement le caractère de nouvelle ligne (et dans le cas de , le NUL), qui $'ab.cd\nef.gh'serait inversé en $'gh.cd\nef.ab', pas $'cd.ab\ngh.ef'ou $'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; doqui n'est pas (encore) POSIX même s'il est supporté par tous les shells POSIX que je connais). C'est juste que cette solution est une traduction directe de zshcelle (divisée en tableau, tableau inversé, joindre des éléments de tableau) mais en utilisant des opérateurs POSIX uniquement. (J'ai changé le string=$string$IFS; set -- $stringen set -- $string$IFScar cela semble fonctionner de manière cohérente entre les shells, merci).
Je vois que Rahul a déjà posté une solution bash native (entre autres), qui est une version plus courte de la première que j'ai inventée:
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"
)
mais je n'ai pas pu m'arrêter là, et j'ai ressenti le besoin d'écrire une solution récursive centrée sur bash:
function reversedots2() {
if [[ $1 =~ ^([^.]*)\.(.*)$ ]]
then
printf %s $(reversedots2 "${BASH_REMATCH[2]}") . "${BASH_REMATCH[1]}"
else
printf %s "$1"
fi
}
Je n'ai pas vu de awkréponse, alors en voici une:
echo 'arg1.arg2.arg3' | awk -F. '{for (i=NF; i>0; --i) printf "%s%s", (i<NF ? "." : ""), $i; printf "\n"}'