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.arg1
Si 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--;
done
Utilisation perl
,
$ echo 'arg1.arg2.arg3.arg4.arg5' | perl -lne 'print join ".", reverse split/\./;'
arg5.arg4.arg3.arg2.arg1
Si 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 sed
invocation:
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), yash
et certainspdksh
shells basés sur ne sont pas POSIX à cet égard en ce qu'ils traitent $IFS
comme 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 zsh
spé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; do
qui 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 zsh
celle (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 -- $string
en set -- $string$IFS
car 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 awk
ré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"}'