2009-10-12 9 views
7

Qui sto affrontando un piccolo problema, voglio passare una stringa contenente spazi bianchi ad un altro programma in modo che l'intera stringa venga trattata come un argomento della riga di comando.Conservazione degli spazi bianchi in una stringa come argomento della riga di comando

Insomma voglio eseguire un comando della seguente struttura attraverso uno script di shell bash: nome_comando -a -b arg1 arg2 -c "arg con spazi bianchi qui"

Ma non importa quanto ci provo, il gli spazi bianchi non sono conservati nella stringa ed è tokenizzato di default. Una soluzione per favore,

edit: Questa è la parte principale del mio script:

#!/bin/bash 

#-------- BLACKRAY CONFIG ---------------# 
# Make sure the current user is in the sudoers list 
# Running all instances with sudo 

BLACKRAY_BIN_PATH='/opt/blackray/bin' 
BLACKRAY_LOADER_DEF_PATH='/home/crozzfire' 
BLACKRAY_LOADER_DEF_NAME='load.xml' 
BLACKRAY_CSV_PATH='/home/crozzfire' 
BLACKRAY_END_POINT='default -p 8890' 
OUT_FILE='/tmp/out.log' 

echo "The current binary path is $BLACKRAY_BIN_PATH" 


# Starting the blackray 0.9.0 server 
sudo "$BLACKRAY_BIN_PATH/blackray_start" 

# Starting the blackray loader utility 
BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "\"$BLACKRAY_END_POINT\""" 

sudo time $BLACKRAY_INDEX_CMD -a $OUT_FILE 

#--------- END BLACKRAY CONFIG ---------# 
+0

Ci dispiace, ma ci hai fornito informazioni troppo poco. Quale shell usi (bash, ksh, csh, ...)? Puoi dire quale comando cerchi di eseguire? Se si tratta di un'utilità UNIX standard, puoi dire la sua versione? –

+0

script bash. Ok qui è quello che sto cercando di fare: .... BLACKRAY_END_POINT = "default -p 8890" .... CMD = "$ BLACKRAY_BIN_PATH/blackray_loader -c $ BLACKRAY_LOADER_DEF_PATH/$ BLACKRAY_LOADER_DEF_NAME -d $ BLACKRAY_CSV_PATH - e \ "$ BLACKRAY_END_POINT \" " ... Ora voglio eseguire il comando precedente in modo che $ BLACKRAY_END_POINT sia trattato come una singola stringa e non venga tokenizzato. $ BLACKRAY_END_POINT è una stringa che contiene spazi e bash la divide in parole diverse. Voglio conservare gli spazi e passare l'intera stringa come un singolo argomento. – crozzfire

+0

Unknown, meet backslash-double-quote (\ "). Backslash-double-quote, meet unknown. –

risposta

1

probabilmente è necessario circondare l'argomento tra virgolette (ad esempio "$ {6}").

seguito OP commento dovrebbe essere "$ BLACKRAY_END_POINT"

+0

Provato. Ma ci vuole ancora solo" default "e non l'intera stringa :( – crozzfire

+0

Sostituisci -e \" $ BLACKRAY_END_POINT \ "" a "\" $ BLACKRAY_END_POINT \ "". È necessario "" per uscire dagli spazi nello script e ulteriori \ "\" per uscire dagli spazi quando il comando viene eseguito – dimba

+0

ancora non ci sono, ci vuole -> "default come arg now (extra open quotes). per l'esecuzione sto usando: sudo time $ CMD -a $ OUT_FILE Se sostituisco $ CMD come "$ CMD", non mi dà alcun errore di file o directory – crozzfire

1

Edit:

Prova:

BLACKRAY_END_POINT="'default -p 8890'" 

o

BLACKRAY_END_POINT='"default -p 8890"' 

o

BLACKRAY_END_POINT="default\ -p\ 8890" 

o

BLACKRAY_END_POINT='default\ -p\ 8890' 

e

BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e $BLACKRAY_END_POINT" 

risposta originale:

è blackray_loader uno script di shell?

Ecco una dimostrazione che si ha a che fare con questo problema sia quando si specifica il parametro e nel maneggiarlo:

un file di testo chiamato "test.txt" (includono i numeri di riga):

1 two words 
2 two  words 
3 two 
4 words 

uno script chiamato "spacetest":

#!/bin/bash 
echo "No quotes in script" 
echo $1 
grep $1 test.txt 
echo 

echo "With quotes in script" 
echo "$1" 
grep "$1" test.txt 
echo 

eseguendolo con ./spacetest "two--------words" (sostituire i trattini con spazi):

No quotes in script 
two words 
grep: words: No such file or directory 
test.txt:1 two words 
test.txt:2 two  words 
test.txt:3 two 

With quotes in script 
two  words 
2 two  words 

Si può vedere che nella sezione "Nessun virgolette" si è cercato di fare grep two words test.txt che interpretato "parole" come un nome di file oltre a "test.txt". Inoltre, lo echo ha lasciato cadere gli spazi extra.

Quando il parametro è quotato, come nella seconda sezione, grep lo ha visto come un argomento (inclusi gli spazi aggiuntivi) e gestito correttamente. E echo ha mantenuto gli spazi aggiuntivi.

Ho usato gli spazi extra, a proposito, solo per aiutare nella dimostrazione.

+0

concordato. Nel mio caso, non sto passando alcun argomento al mio script di bash, invece sto codificando un argomento (con spazi) che deve essere passato ad un comando.Questo comando (blackray_loader) è chiamato con il mio script bash. per preservare gli spazi bianchi dell'argomento e passarlo come un'intera stringa: – crozzfire

+0

Questo è esattamente ciò che sto dimostrando. Nello script sopra, 'grep' è una supplente per il tuo' blackray_loader'. Il tuo comando dovrà gestire correttamente i parametri. Tuttavia vedi la modifica per un'altra cosa da provare. –

5

Si sta verificando questo problema perché si memorizza il comando in una variabile, quindi si espande in seguito; a meno che non ci sia una buona ragione per fare questo, non lo fanno :

sudo time $BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "$BLACKRAY_END_POINT" -a $OUT_FILE 

Se è davvero necessario per memorizzare il comando e utilizzare in un secondo momento, ci sono diverse opzioni; il wiki di bash-hackers.org ha un good page on the subject. Sembra a me come la più utile è di mettere il comando in una matrice piuttosto che una semplice variabile:

BLACKRAY_INDEX_CMD=($BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "$BLACKRAY_END_POINT") 

sudo time "${BLACKRAY_INDEX_CMD[@]}" -a $OUT_FILE 

Ciò evita tutta la confusione tra spazi di separazione-parola e spazi-within-parole perchè parole non sono separati da spazi: sono in elementi separati dell'array. L'espansione dell'array tra virgolette con il suffisso [@] mantiene tale struttura.

(A proposito, un'altra opzione sarebbe quella di utilizzare le virgolette sfuggiti un po 'come si sta facendo, quindi eseguire il comando con eval Non fare questo,.. È un buon modo per introdurre bug di analisi strani)

3

ho un suggerimento:

# iterate through the passed arguments, save them to new properly quoted ARGS string 
while [ -n "$1" ]; do 
    ARGS="$ARGS '$1'" 
    shift 
done 

# invoke the command with properly quoted arguments 
my_command $ARGS 
+3

Questo non funziona affatto - la shell analizza le virgolette prima che espanda le variabili, quindi se ci sono virgolette nei valori della variabile non vengono trattate come virgolette, solo caratteri regolari. Fondamentalmente, è troppo tardi per loro di avere l'effetto desiderato. Quello che succede in realtà è che vengono passati al comando come parte dell'argomento, che non è quello che vuoi. –

-1

un post sul altri blog mi ha salvato per questo problema spazi bianchi: http://logbuffer.wordpress.com/2010/09/23/bash-scripting-preserve-whitespaces-in-variables/

per impostazione predefinita, gli spazi vuoti vengono Trimed:

"La causa di questo comportamento è la variabile di shell interna $ IFS (Internal Field Separator), che per impostazione predefinita è lo spazio bianco, scheda e nuova riga. Per conservare tutti gli spazi bianchi contigui è necessario impostare l'IFS per qualcosa di diverso "

Con IFS bypass:

bash> IFS='%' 
bash> echo $VAR1 
abc  def gh ijk 
bash>unset IFS 
bash> 

Funziona meravigliosamente per il mio caso comando:

su - user1 -c 'test -r "'${filepath}'"; ....' 

Spero che questo aiuti

+0

Interrompere la diffusione di hack ritardati, per favore. Stai dimostrando chiaramente che non capisci l'importanza delle virgolette. _Per impostazione predefinita, gli spazi bianchi sono tagliati_: SBAGLIATO. Senza virgolette, andrai sotto suddivisione di parole e espansioni di nomi di file. Cura questo con le virgolette: 'VAR1 =" abc def gh ijk "; echo "$ VAR1" '. Ora funziona. Inoltre, come spiegheresti cosa succede nel caso di un jolly: 'VAR1 = '*'; echo $ VAR1' vs 'VAR1 = '*'; echo "$ VAR1" '? Anche con la tua cosa 'IFS', otterrai lo stesso risultato orribile:' IFS =%; VAR1 = '*'; echo $ VAR1'. Basta usare più citazioni. Periodo. –

+0

Puoi spiegarmi perché in questo caso il filepath è ridotto: 'test -r' '$ {filepath}' "'? – Kloe2378231

+0

Devi capire come funzionano le citazioni. Non ci sono nidificazioni per le virgolette. Prenderò il tuo comando completo: 'su - user1 -c 'test -r"' $ {filepath} '";''. Se 'filepath' contiene spazi, ad esempio' filepath = 'a b'', quindi quando si esegue 'su - user1 -c' test -r" '$ {filepath}' "; '', bash si espanderà al seguente parole: 'su',' -', 'utente1',' -c', 'test -r" a', 'b"; '. Non quello che vuoi. Con 'IFS =%' è _seems_ che funziona, ma fallirà se 'filepath' contiene caratteri jolly o il simbolo'% 'o il simbolo' "' (o altri globi). –

0

Di seguito è il mio examp il riavvio di uno script tramite exec su USER o exec su - USER. Ospita:

  • essere chiamato da un percorso relativo o directory corrente
  • spazi nel nome dello script e gli argomenti
  • singole e doppie virgolette negli argomenti, senza fughe folli come: \\"

# 
# This script should always be run-as a specific user 
# 
user=jimbob 
if [ $(whoami) != "$user" ]; then 
    exec su -c "'$(readlink -f "$0")' $(printf " %q" "[email protected]")" - $user 
    exit $? 
fi 
Problemi correlati