2009-09-22 15 views
11

me encontré con el siguiente problema: Estoy escribiendo un script bash de Linux, que hace lo siguiente:BASH: Tira carácter de nueva línea de cuerda (leer línea)

  • Leer línea del archivo
  • de Gaza el carácter \n desde el final de la línea que acaba de leer
  • ejecutar el comando que hay ahí

Ejemplo: commands.txt

ls 
ls -l 
ls -ltra 
ps as 

La ejecución del archivo fiesta debe conseguir la primera línea, y ejecutarlo, pero mientras que el \n presente, el shell solo salidas "comando no encontrado: ls" Esa parte de la secuencia de comandos se parece a esto

read line 

     if [ -n "$line" ]; then #if not empty line 

       #myline=`echo -n $line | tr -d '\n'` 
       #myline=`echo -e $line | sed ':start /^.*$/N;s/\n//g; t start'` 

       myline=`echo -n $line | tr -d "\n"` 
       $myline #execute it 

       cat $fname | tail -n+2 > $fname.txt 
       mv $fname.txt $fname 
     fi 

Comentó que tiene las cosas que probé antes de preguntar SO. Alguna solución? Estoy rompiendo mi cerebro durante el último par de horas más de esto ...

+0

ha intentado simplemente '$ line' solo? – knittl

+0

Por supuesto que sí. Pero dice "comando no encontrado: ls " –

+0

Todo lo que se necesita es: 'myline =" $ (echo -n "$ line") "' (con comillas inversas en lugar de '$()' si lo desea) – jnylen

Respuesta

17

Siempre me gusta perl -ne 'chomp and print', para recortar nuevas líneas. Agradable y fácil de recordar.

p. Ej. ls -l | perl -ne 'chomp and print'

Sin embargo

no creo que es su problema aquí, sin embargo. Aunque no estoy seguro de entender cómo está pasando los comandos en el archivo a la 'lectura' en su script de shell.

Con un guión de prueba de mi propia como esto (test.sh)

read line 
if [ -n "$line" ]; then 
    $line 
fi 

y un archivo de entrada de ejemplo como éste (test.cmds)

ls 
ls -l 
ls -ltra 

Si lo ejecuto como esto ./test.sh < test.cmds, veo el resultado esperado, que es ejecutar el primer comando 'ls' en el directorio de trabajo actual.

¿Quizás su archivo de entrada tiene caracteres adicionales no imprimibles en él?

mío se parece a esto

od -c test.cmds 
0000000 l s  \n l s  - l \n l s  - l t 
0000020 r a \n              
0000023 

Desde sus comentarios a continuación, que sospecha que puede tener retornos de carro ("\ r") en el archivo de entrada, que no es lo mismo que una nueva línea. ¿El archivo de entrada está originalmente en formato DOS? Si es así, entonces necesita convertir la línea DOS de 2 bytes que termina "\ r \ n" al UNIX de un solo byte, "\ n" para lograr los resultados esperados.

Debería poder hacer esto al cambiar "\ n" por "\ r" en cualquiera de sus líneas comentadas.

+1

Olvidé mencionar que el archivo está escrito desde Windows en un recurso compartido de samba y olvidé por completo que debería buscar un '\ r' en lugar de' \ n'. ¡Hasta un voto mío y muchas gracias! –

0

aunque no trabaja para ls, recomiendo echar un vistazo a find 's -print0 opción

2

He intentado esto:

read line 
echo -n $line | od -x 

Para la entrada 'xxxx', me sale:

0000000 7878 7878 

Como se puede ver, no hay en el \n fin del contenido de la variable. Sugiero ejecutar el script con la opción -x (bash -x script). Esto imprimirá todos los comandos mientras se ejecutan.

[EDIT] Su problema es que ha editado commands.txt en Windows. Ahora, el archivo contiene CRLF (0d0a) como delimitadores de línea que confunde read (y ls\r no es un comando conocido). Use dos2unix o similar para convertirlo en un archivo Unix.

+0

Lo que pasa es que no leo en el teclado. Cambio mi STDIN a un archivo (el comando.txt desde arriba) y si hago eco de la línea $ entre '' Obtengo la salida 'ls ' –

+0

La salida que obtengo 'echo -n $ línea | od -x' es "0000000 736c 000d 0000003" –

+1

El 0d es un retorno de carro. No es lo mismo que una nueva línea – cms

1

necesita comando eval


#!/bin/bash -x 

while read cmd 
do 
if [ "$cmd" ] 
then 
    eval "$cmd" 
fi 
done 

Corrí como
./script.sh < archivo.txt

Y archivo.txt era:

 
ls 
ls -l 
ls -ltra 
ps as 
+0

'eval' tampoco funcionará –

0

La siguiente secuencia de comandos funciona (al menos para mí):

#!/bin/bash 

while read I ; do if [ "$I" ] ; then $I ; fi ; done ; 
12

Alguien ya escribió un programa que ejecuta los comandos shell: archivo sh

Si realmente sólo desea ejecutar la primera línea de un archivo: head -n 1 file |sh

Si su problema es retornos de carro: tr -d '\r' <file |sh

+0

Sí, por supuesto, pero esa parte de mi archivo por lotes. Es más que un simple comando de ejecución desde el archivo, porque si fuera solo esto, lo he usado con seguridad solo 'sh' –

2

también puede tratar de sustituir los retornos de carro con saltos de línea sólo con órdenes internas del golpe:

line=$'a line\r' 
line="${line//$'\r'/$'\n'}" 
#line="${line/%$'\r'/$'\n'}"  # replace only at line end 
printf "%s" "$line" | ruby -0777 -n -e 'p $_.to_s' 
Cuestiones relacionadas