Caracteres de la pestaña eco en script bash

313

¿Cómo hago eco de uno o más caracteres de tabulación usando un script bash? Cuando ejecuto este código

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

entiendo esto

res=[ x] # that is [<space>x]
kalyanji
fuente

Respuestas:

529
echo -e ' \t '

repetirá 'espacio de tabulación espacio nueva línea' ( -esignifica 'permitir la interpretación de escapes de barra invertida'):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|
Johannes Weiss
fuente
Gracias Johannes Me ayudaste a encontrar esta solución: res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji
2
¿Sabes por qué echo -eno funciona desde Makefiles?
dma_k
23
Esto se debe a echo -eque no es POSIX y las makellamadas /bin/shque normalmente no se usan en el programa se usan de forma interactiva y normalmente no se han -eimplementado. Para portabilidad, use printf '\t'en su lugar.
Jo So
En Darwin (macOS), la manpágina del echocomando no menciona la opción -e. Sin embargo, esta opción es aceptada.
ePi272314
75

Uso printf, no echo.

Hay varias versiones diferentes del echocomando. Existe /bin/echo(que puede ser o no la versión GNU Coreutils, dependiendo del sistema), y el echocomando está integrado en la mayoría de los shells. Las diferentes versiones tienen diferentes formas (o ninguna) para especificar o deshabilitar escapes para los caracteres de control.

printf, por otro lado, tiene mucha menos variación. Puede existir como un comando, por lo general /bin/printf, y está integrado en algunos shells (bash y zsh lo tienen, tcsh y ksh no), pero las diversas versiones son mucho más similares entre sí que las diferentes versiones de echo. Y no tiene que recordar las opciones de línea de comandos (con algunas excepciones; GNU Coreutils printf acepta --versiony --help, y el bash printf incorporado acepta -v varalmacenar la salida en una variable).

Por su ejemplo:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

Y ahora es tiempo de admitir que echofuncionará igual de bien para el ejemplo que está preguntando; solo necesita poner comillas dobles alrededor del argumento:

echo "[$res]"

como escribió kmkaplan (hace dos años y medio, ¡acabo de darme cuenta!). El problema con tus comandos originales:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

no está con echo; es que el caparazón reemplazó la pestaña con un espacio antes de echoverlo.

echoestá bien para una salida simple, como echo hello world, pero debe usarlo printfcuando quiera hacer algo más complejo. Usted puede obtener echoa trabajar, pero el código resultante es probable que falle cuando se ejecuta con una diferente echoaplicación o un shell diferente.

Keith Thompson
fuente
1
Me gustó este, me permite usar el conocimiento de printf y todos los especificadores de formato.
Arun
@JezenThomas: No está más votado porque responde la pregunta de una manera diferente a la solicitada. La pregunta menciona específicamente echo, y echo no es un verbo sino un comando.
Paulo Neves
@PauloNeves: Diría que se usa como un verbo en la pregunta: "¿Cómo hago eco de uno o más caracteres de tabulación usando un script bash?"
Keith Thompson
34

Pon tu cadena entre comillas dobles :

echo "[$res]"
kmkaplan
fuente
1
lo mismo aquí, esto es lo que probé primero. -aunque funcionó bien
froderik
2
@kmkaplan funciona para mí en zsh - falla para mí en bash
Kal
34

También puedes probar:

echo Hello$'\t'world.
jbatista
fuente
44
+1 para una solución más general. ¡He estado usando bash durante años y acabo de aprender esto ahora!
Aryeh Leib Taurog
Esta es una respuesta mucho más general que la aceptada, ya que se puede usar sin eco.
jwan
22

necesitas usar -e flag para echo, entonces puedes

echo -e "\t\t x"
Aprendizaje
fuente
16

Desde la página de manual de bash:

Las palabras de la forma $ 'string' se tratan especialmente. La palabra se expande a una cadena, con los caracteres con barra invertida reemplazados según lo especificado por el estándar ANSI C.

Entonces puedes hacer esto:

echo $'hello\tworld'
esoriano
fuente
¿Por qué funciona esto en el cli pero no en un script bash?
Freek
13

Usar la palabra por palabra de pulsaciones de teclas, ^V( CTRL+V, C-v, lo que sea ).

Cuando escribe ^Ven el terminal (o en la mayoría de los editores de Unix), el siguiente carácter se toma literalmente . Puede usar esto para escribir un carácter de tabulación literal dentro de una cadena que está repitiendo.

Algo así como los siguientes trabajos:

echo "^V<tab>"     # CTRL+V, TAB

Documentos bash ( qv , "inserción-citada")

entre comillas (Cq, Cv) Agregue el siguiente carácter que escriba a la línea textualmente. Así es como se insertan secuencias de teclas como Cq, por ejemplo.

nota al margen: de acuerdo con esto, ALT+TAB debería hacer lo mismo, pero todos hemos vinculado esa secuencia al cambio de ventana, por lo que no podemos usarla

tab-insert (M-TAB) Inserta un carácter de tabulación.

-

Nota: puedes usar esta estrategia con todo tipo de personajes inusuales. Como un retorno de carro:

echo "^V^M"        # CTRL+V, CTRL+M

Esto se debe a que el retorno de carro es ASCII 13 y M es la decimotercera letra del alfabeto, por lo que cuando escribe ^M, obtiene el decimotercer carácter ASCII. Puede verlo en acción usando ls^M, en una solicitud vacía, que insertará un retorno de carro, haciendo que la solicitud actúe como si presionara retorno. Cuando estos caracteres se interpretan normalmente, textualmente se obtiene el carácter literal.

rico remer
fuente
1
Ojalá pudiera darte más votos a favor para este. No quería usar un -e en mis argumentos en este caso, y esto funciona muy bien. ¡Gracias!
Aaron R.
"... la mayoría de los editores de Unix"? Intenté ingresar esto con vi y emacs y tampoco dio los resultados deseados.
GreenMatt
Eso es tan genial! Y me salvó el día cuando intentaba usar greppara atrapar líneas que contenían tabcaracteres.
Joël
11

Usar echo para imprimir valores de variables es una trampa común de Bash. Link de referencia:

http://mywiki.wooledge.org/BashPitfalls#echo_.24foo

Anónimo
fuente
Genial, me gustan los "BashPitfalls", una gran pieza de material y alivian mucho el dolor de mi trabajo diario.
Jerry Tian
+1 porque esto es tan cierto. Pero tenga en cuenta que la cadena kalyanji comienza con un "[" y no contiene ningún "\".
kmkaplan
2

Si desea usar echo "a\tb"en un script, ejecute el script como:

# sh -e myscript.sh

Alternativamente, puede otorgarle a myscript.sh el permiso de ejecución y luego ejecutar el script.

# chmod +x myscript.sh
# ./myscript.sh
ATC
fuente
0
res="\t\tx"
echo -e "[${res}]"
Yanghaogn
fuente