BASH: Tira caractere de nova linha de string (linha ler)
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 ...
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 E file.txt foi:
./script.sh 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 ;