Estou tentando gerar um arquivo que eu possa anexar ao visudo. A tarefa em si não é muito importante, pois estou apenas tentando me aprofundar um pouco mais no Bash. Meu script atual se parece com isso:
#!/bin/bash
path=/bin/ansible*
declare -a commands=()
for command in $path; do
commands+=($command)
done
echo ${commands[@]} > ~/commands.txt
que produz:
/bin/ansible /bin/ansible-config /bin/ansible-connection /bin/ansible-console...
Gostaria que a saída do script fosse parecida com:
/bin/ansible, /bin/ansible-config, /bin/ansible-connection, /bin/ansible-console...
Acho que estou complicando demais essa tarefa. Já vi pessoas usando awk e sed, mas pelo que vi awk parece funcionar melhor com colunas de dados e sed é muito confuso. Qualquer conselho seria apreciado.
Em vez disso, tente usar
zsh
o que tem um operador interno para unir os elementos de uma matriz com strings arbitrárias.Ou sem a variável intermediária, usando uma função anônima:
Em
bash
, o único operador de junção integrado é o estilo Korn"${array[*]}"
, que une os elementos de uma matriz com o primeiro caractere de,$IFS
mas nenhum, para unir strings com mais de um caractere, como", "
aqui.Ele não tem
N
o qualificador do zsh e ainda não copiou o do ksh~(N)
, mesmo comshopt -s extglob
, então você precisa definir anullglob
opção globalmente para globs com no-match para expandir para nada.Ou use perl, por exemplo (em qualquer shell, até mesmo bash, embora você também possa usar
sh
, que certamente pode ser encontrado em qualquer sistema):Você poderia dizer isso. Usar globbing como em
/bin/ansible*
já lhe dá um array. Você não precisa copiar elementos daquele array para outro array!Então, você pode diretamente
É isso.
Isto é, se você quiser ignorar o fato de que você falhará quando não houver um arquivo correspondente e, de qualquer forma, terá um final
,
.Se você quiser corrigir ambos os problemas:
Não expanda um curinga que pode retornar múltiplos valores em uma string escalar. Use um array como você fez em outro lugar.
No caso trivial em que você está gerando um valor de string com uma vírgula depois dele, você pode fazer isto:
No entanto, para o caso realista em que a vírgula é um separador em vez de um terminador, você precisa removê-la do último elemento. Essa abordagem evita usar um loop:
Algumas notas,
shopt nullglob
opção garante que se um curinga for usado sem correspondências, o resultado será uma string vazia em vez da correspondência do padrão original, incluindo os curingas como caracteres literais (tenteecho bin/ansible*
e entãoecho bin/rhubarb*
; observe que o segundo retorna a string original, incluindo o*
caractere)echo
como uma maneira rápida de produzir os elementos do array. Cuidado ao usá-lo para valores que começam com-
(ou em alguns casos que contêm sequências de escape como\r
ou\n
)