inverser l’ordre des caractères dans une chaîne

Dans la chaîne “12345”, sortez la chaîne “54321”. De préférence sans outils tiers et regex.

Je sais que vous avez dit “sans outils tiers”, mais parfois, un outil est trop évident, et il est installé par défaut sur la plupart des systèmes Linux:

[madhatta@risby tmp]$ echo 12345|rev 54321 

Simple:

 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" 

Sortie:

 $ bash rev var: 12345, rev: 54321 

rev | tail -r rev | tail -r (BSD) ou rev | tac rev | tac (GNU) renverse aussi les lignes:

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

Si LC_CTYPE est C, rev inverse les octets des caractères multi-octets:

 $ LC_CTYPE=C rev < << あの   め  $ export LC_ALL=C; LC_ALL=en_US.UTF-8 rev <<< あののあ 

Présume qu’une variable ‘var’ a la valeur ‘123’

 var="123" 

Inverser la chaîne et stocker dans une nouvelle variable ‘rav’:

 rav=$(echo $var | rev) 

Vous verrez que le ‘rav’ a la valeur de ‘321’ en utilisant l’écho.

 echo $rav 

Cela inverse la chaîne “in place”:

 a=12345 len=${#a} for ((i=1;i 

ou la troisième ligne pourrait être:

 for ((i=0;i 

ou

 for ((i=1;i 

Une solution bash améliorant la réponse à @osdyng (mon édition n’a pas été acceptée):

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

Ou une boucle (bash) encore plus simple:

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

Une solution POSIX:

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

Remarque: Cela fonctionne sur les chaînes multi-octets. Les solutions de découpe ne fonctionnent que dans les chaînes ASCII (1 octet).

Cela peut bien sûr être raccourci, mais il devrait être simple à comprendre: l’ print finale ajoute la nouvelle ligne.

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

Personne ne semble avoir mis en place une solution sed , alors en voici une qui fonctionne dans une version non GNU sed (donc je ne la considérerais pas comme une “tierce partie”). Il capture des caractères uniques en utilisant le regex . , mais c’est la seule regex.

En deux étapes:

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

Cela utilise la substitution au format bash pour inclure les nouvelles lignes dans les scripts (puisque la question est balisée). Il commence par séparer la chaîne d’entrée en une ligne par caractère, puis en insérant chaque caractère dans le début du tampon de mise en attente.

  • x échange l’espace de maintien et l’espace du motif, et
  • H H ajoute l’espace de motif (actuel) à l’espace d’attente.

Donc, pour chaque personnage, nous plaçons ce caractère dans l’espace d’attente, puis y ajoutons l’ancien espace d’attente, inversant ainsi l’entrée. La dernière commande supprime les nouvelles lignes afin de reconstruire la chaîne d’origine.

Cela devrait fonctionner pour n’importe quelle chaîne, mais elle concaténerait les entrées multilignes en une seule chaîne de sortie.

Pour ceux sans rev (recommandé), il existe la solution awk simple suivante qui divise les champs sur la chaîne null (chaque caractère est un champ séparé) et imprime en sens inverse:

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

Le code awk ci-dessus est conforme à POSIX. Comme une plainte concernant l’implémentation de awk est garantie sur tous les systèmes d’exploitation compatibles POSIX, le code ne doit donc pas être considéré comme “tiers”. Ce code sera probablement plus concis et compréhensible qu’une solution pure POSIX sh (ou bash ).

(; Je ne sais pas si vous considérez la chaîne nulle comme -F une regex …;)

Si var=12345 :

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

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

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

Exécuter:

 $ rev var: 12345, rev: 54321 

Quelques méthodes simples pour inverser une chaîne

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

Convertir en valeurs hexadécimales puis inverser

 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