bash - programacion - invertir el orden de los caracteres en una cadena
invertir una cadena en c (11)
Algunos métodos simples de revertir una cadena
echo ''!!!esreveR si sihT'' | grep -o . | tac | tr -d ''/n'' ; echo
echo ''!!!esreveR si sihT'' | fold -w 1 | tac | tr -d ''/n'' ; echo
Convertir a valores hexadecimales y luego invertir
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
En la cadena "12345", fuera de la cadena "54321". Preferiblemente sin herramientas de terceros y regex.
Esto invierte la cadena "en su lugar":
a=12345
len=${#a}
for ((i=1;i<len;i++)); do a=$a${a: -i*2:1}; done; a=${a:len-1}
echo $a
o la tercera línea podría ser:
for ((i=0;i<len;i++)); do a=${a:i*2:1}$a; done; a=${a:0:len}
o
for ((i=1;i<len;i++)); do a=${a:0:len-i-1}${a: -i:i+1}${a:len-i-1:1}; done
Nadie parece haber publicado una solución sed
, así que aquí hay una que funciona en sed no GNU (por lo que no la consideraría "tercero"). Captura solo caracteres utilizando la expresión regular .
, pero esa es la única expresión regular.
En dos etapas:
$ echo 123456 | sed $''s/./&///n/g'' | sed -ne $''x;H;${x;s///n//g;p;}''
654321
Esto utiliza la sustitución del formato bash para incluir nuevas líneas en los scripts (ya que la pregunta está etiquetada como bash ). Funciona separando primero la cadena de entrada en una línea por carácter, y luego insertando cada carácter en el comienzo del búfer de retención.
-
x
intercambia el espacio de retención y el espacio de patrón, y -
H
H agrega el espacio del patrón (actual) al espacio de retención.
Por lo tanto, para cada personaje, colocamos ese carácter en el espacio de retención, luego le agregamos el espacio de retención anterior, invirtiendo así la entrada. El comando final elimina las nuevas líneas para reconstruir la cadena original.
Esto debería funcionar para cualquier cadena única, pero concatenará la entrada de varias líneas en una sola cadena de salida.
Para aquellos sin rev (recomendado), existe la siguiente solución awk simple que divide los campos en la cadena nula (cada carácter es un campo separado) y se imprime al revés:
awk -F '''' ''{ for(i=NF; i>0; i--) printf("%s", $i); print "" }''
El código awk anterior es compatible con POSIX. Como se garantiza que una implementación awk compatible se encuentra en todos los sistemas operativos compatibles con POSIX, la solución no debe considerarse como "de terceros". Este código probablemente sea más conciso y comprensible que una solución pura POSIX sh (o bash ).
(; No sé si considera que la cadena nula es -F una expresión regular ...;)
Por supuesto, esto puede acortarse, pero debería ser fácil de entender: la print
final agrega la nueva línea.
echo 12345 | awk ''{for (i = length($0); i > 0; i--) {printf("%s", substr($0, i, 1));} print "";}''
Sé que usted dijo "sin herramientas de terceros", pero a veces una herramienta es obviamente la correcta, además de que está instalada en la mayoría de los sistemas Linux por defecto:
[madhatta@risby tmp]$ echo 12345|rev
54321
Sencillo:
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"
Salida:
$ bash rev
var: 12345, rev: 54321
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"
Ejecutarlo:
$ rev
var: 12345, rev: 54321
Supongamos que una variable ''var'' tiene el valor ''123''
var="123"
Invierta la cadena y almacene en una nueva variable ''rav'':
rav=$(echo $var | rev)
Verás que ''rav'' tiene el valor de ''321'' usando eco.
echo $rav
Una solución de bash que mejora sobre la respuesta de @osdyng (mi edición no fue aceptada):
var="12345" rev=""
for(( i=0 ; i<${#var} ; i++ )); do rev="${var:i:1}$rev"; done
echo "var: $var, rev: $rev"
O un bucle aún más simple (bash):
var=$1 len="${#var}" i=0 rev=""
while (( i<len )); do rev="${var:i++:1}$rev"; done
echo "var: $var, rev: $rev"
Una solución POSIX:
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"
Nota: Esto funciona en cadenas de múltiples bytes. Las soluciones de corte solo funcionarán en cadenas ASCII (1 byte).
rev | tail -r
rev | tail -r
(BSD) o rev | tac
rev | tac
(GNU) también líneas inversas:
$ rev <<< $''12/n34'' | tail -r
43
21
$ rev <<< $''12/n34'' | gtac
43
21
Si LC_CTYPE es C, rev revierte los bytes de los caracteres multibyte:
$ LC_CTYPE=C rev <<< あの
��め�
$ export LC_ALL=C; LC_ALL=en_US.UTF-8 rev <<< あの
のあ