Domanda

mi imbattei nel seguente problema: Sto scrivendo uno script bash Linux, che esegue le seguenti operazioni:

  • Leggi riga dal file
  • Striscia il carattere \n dalla fine della linea appena letto
  • Eseguire il comando che c'è dentro

Esempio: ecommands.txt

ls
ls -l
ls -ltra
ps as

L'esecuzione del file bash dovrebbe ottenere la prima riga, ed eseguirlo, ma mentre la \n presente, il guscio appena uscite "comando non trovato: ls" Quella parte dello script simile a questo

 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

Commentate avete le cose che ho provato prima di chiedere SO. Eventuali soluzioni? Sto distruggendo il mio cervello per l'ultimo paio di ore su questo ...

È stato utile?

Soluzione

mi piace sempre perl -ne 'chomp and print', per il taglio a capo. Bello e facile da ricordare.

es. ls -l | perl -ne 'chomp and print'

Tuttavia

Non credo che sia il problema qui però. Anche se non sono sicuro di aver capito come si sta passando i comandi nel file attraverso la 'lettura' nel vostro script di shell.

Con uno script di test della mia come questo (test.sh)

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

e un file di input di esempio come questo (test.cmds)

ls 
ls -l
ls -ltra

Se corro come questo ./test.sh < test.cmds, vedo il risultato atteso, che è quello di eseguire il 'ls' primo comando nella directory di lavoro corrente.

Forse il vostro file di input ha caratteri non stampabili supplementari in esso?

miniera assomiglia a questo

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

Da vostri commenti qui sotto, ho il sospetto si può avere ritorni a capo ( "\ r") nel file di input, che non è la stessa cosa di un ritorno a capo. È il file di input originariamente in formato DOS? Se è così, allora avete bisogno di convertire la linea di DOS 2 byte finale "\ r \ n" al singolo byte UNIX uno, "\ n" per ottenere i risultati attesi.

Si dovrebbe essere in grado di fare questo scambiando il "\ n" per "\ r" in uno dei tuoi righe di commento fuori.

Altri suggerimenti

Qualcuno ha già scritto un programma che esegue comandi di shell: file di sh

Se davvero desidera solo per eseguire la prima riga di un file: head -n 1 file |sh

Se il problema è a capo-rendimenti: tr -d '\r' <file |sh

Ho provato questo:

read line
echo -n $line | od -x

Per l'ingresso 'xxxx', ottengo:

0000000 7878 7878

Come si può vedere, non v'è alcuna \n alla fine del contenuto della variabile. Vi suggerisco di eseguire lo script con l'opzione -x (bash -x script). Questo stamperà tutti i comandi mentre vengono eseguiti.

[EDIT] Il tuo problema è che si è modificato ecommands.txt su Windows. Ora, il file contiene CRLF (0d0a) come delimitatori di linea che confonde read (e ls\r non è un comando noto). Utilizzare dos2unix o simili a trasformarlo in un file Unix.

Si può anche provare a sostituire ritorni a capo con a capo solo utilizzando builtin Bash:

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' 

è necessario il comando eval


#!/bin/bash -x

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

ho eseguito come
./script.sh

E file.txt era:

ls
ls -l
ls -ltra
ps as

anche se non lavorare per ls, vi consiglio di dare un'occhiata al find s 'opzione -print0

Il seguente script funziona (almeno per me):

#!/bin/bash

while read I ; do if [ "$I" ] ; then $I ; fi ; done ;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top