Parâmetro de aspas simples com script Bash com valor de globbing

5

Estou tentando escrever um script de pesquisa de código, com diretórios e arquivos configuráveis que são excluídos. A parte principal deste script é a seguinte linha:

out=$(grep -TInr$C$W --color=always \
    --exclude={translations} \
    --exclude-dir={build,tmp} \
    "$SEARCH")

As variáveis $C e $W são definidas por parâmetros de script para configurar a diferenciação de maiúsculas e minúsculas e a correspondência exata de palavras, e $SEARCH é simplesmente os parâmetros restantes, que serão a sequência de pesquisa. No entanto, minha implementação para ignorar certos arquivos ainda não funciona.

Para excluir arquivos da pesquisa, estou tentando usar um arquivo ~/.codesearch_config , que é assim:

#!/bin/bash

if [[ $PWD == "$HOME/project"* ]]; then
    exclude_directories={.git,build,tmp}
    exclude_files={translations}
fi

A ideia aqui, é claro, é que dependendo do seu diretório de trabalho atual, um determinado conjunto de exclusões será carregado. Mas ao tentar adicionar isso ao script como tal:

--exclude=$exclude_files

o parâmetro inteiro será colocado em aspas simples por bash (testado com a opção -x para depurar) assim:

grep -TInrw --color=always '--exclude={translations}' '--exclude-dir={build,tmp}' search_term

O que eu quero fazer é expandir isso para --exclude-dir=build --exclude-dir=tmp . Se eu adicionar manualmente os valores dessas variáveis $exclude_ ao comando, ele se expandirá muito bem; O problema é que as aspas simples são colocadas em torno do meu parâmetro e glob. Como posso evitar isso?

    
por Erik S 04.04.2016 / 13:25

1 resposta

3

Tente usar arrays para suas exclusões e expanda-as em - exclude-dir e --exclude options.

por exemplo. no seu script ~/.codesearch_config (presumivelmente isso é originado pelo seu script principal?):

#! /bin/bash

# temporary array variables
declare -a __exclude_directories
declare -a __exclude_files

if [[ "$PWD" == "$HOME/project"* ]]; then
    __exclude_directories=(.git build tmp)
    __exclude_files=(translations)
elif [[ "$PWD" == "/some/where/else" ]]; then
    __exclude_directories=(foo bar)
    __exclude_files=(abc.txt def.txt xyz.txt)
fi

exclude_directories=''
exclude_files=''

for i in "${__exclude_directories[@]}" ; do
    exclude_directories+=" --exclude-dir '$i'"
done

for i in "${__exclude_files[@]}" ; do
    exclude_files+=" --exclude '$i'"
done

unset __exclude_directories
unset __exclude_files

# comment out or delete the next two lines after you've verified
# that the output is correct.
echo $exclude_directories 
echo $exclude_files

Mais tarde, você os usaria assim:

out=$(grep -TInr$C$W --color=always \
      $exclude_files \
      $exclude_directories \
      "$SEARCH")

Observação: não há cotações em torno das variáveis $exclude_* aqui, caso contrário, elas serão tratadas como um argumento único cada, em vez de vários argumentos --exclude e --exclude-dir . Essa é uma das poucas situações em que você não deseja e não deve citar duas vezes suas variáveis (ou seja, quando estiver construindo uma linha de comando em uma variável ou variáveis).

Em quase todos os outros casos, você deve, por uma questão de hábito profundamente enraizado, citar duas vezes suas variáveis.

    
por 04.04.2016 / 15:53