Pergunta

topei com o seguinte problema: Eu estou escrevendo um script bash Linux que faz o seguinte:

  • linha de leitura de arquivo
  • Faixa do personagem \n a partir do final da linha acabou de ler
  • Execute o comando que está lá dentro

Exemplo: commands.txt

ls
ls -l
ls -ltra
ps as

A execução do arquivo festa deve começar na primeira linha, e executá-lo, mas enquanto o \n presente, o shell apenas gera "comando não encontrado: ls" Essa parte dos olhares de script como este

 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

Comentada você tem as coisas que eu tentei antes de pedir SO. Todas as soluções? Eu estou quebrando meu cérebro para o último par de horas sobre isso ...

Foi útil?

Solução

Eu gosto sempre perl -ne 'chomp and print', para novas linhas de corte. Agradável e fácil de lembrar.

por exemplo. ls -l | perl -ne 'chomp and print'

No entanto

Eu não acho que é o seu problema aqui embora. Embora eu não tenho certeza se eu entendo como você está passando os comandos no arquivo até a 'ler' em seu script shell.

Com um script de teste do meu próprio como este (test.sh)

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

e um arquivo de entrada de amostra assim (test.cmds)

ls 
ls -l
ls -ltra

Se eu executá-lo como este ./test.sh < test.cmds, vejo o resultado esperado, que é executar o primeiro comando 'ls' no diretório de trabalho atual.

Talvez o seu arquivo de entrada tem caracteres não imprimíveis adicionais nele?

mina parece com isso

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

De seus comentários abaixo, eu suspeito que você pode ter retornos de carro ( "\ r") em seu arquivo de entrada, o que não é a mesma coisa que uma nova linha. É o arquivo de entrada originalmente em formato DOS? Se sim, então você precisa converter a linha DOS 2 byte fim "\ r \ n" ao único byte UNIX um, "\ n" para alcançar os resultados esperados.

Você deve ser capaz de fazer isso trocando o "\ n" para "\ r" em qualquer das suas linhas comentadas.

Outras dicas

Alguém já escreveu um programa que executa comandos shell: arquivo sh

Se você realmente só quer executar a primeira linha de um arquivo: head -n 1 file |sh

Se o seu problema é transporte de volta: tr -d '\r' <file |sh

Eu tentei isso:

read line
echo -n $line | od -x

Para a entrada 'xxxx', eu recebo:

0000000 7878 7878

Como você pode ver, não há \n no final o conteúdo da variável. Sugiro para executar o script com o -x opção (bash -x script). Isto irá imprimir todos os comandos como eles são executados.

[EDIT] O seu problema é que você editou commands.txt no Windows. Agora, o arquivo contém CRLF (0d0a) como delimitadores de linha que confunde read (e ls\r não é um comando conhecido). Use dos2unix ou similar para transformá-lo em um arquivo Unix.

Você também pode tentar substituir retornos de carro com novas linhas usando apenas builtins 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' 

você precisa comando eval


#!/bin/bash -x

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

Eu corri-lo como
./script.sh

E file.txt foi:

ls
ls -l
ls -ltra
ps as

embora não trabalhar para ls, eu recomendo ter um olhar para find 's opção -print0

As seguintes obras de script (pelo menos para mim):

#!/bin/bash

while read I ; do if [ "$I" ] ; then $I ; fi ; done ;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top