2011-09-06 12 views
109

Come si utilizzano le linee di continuazione bash?Linee di continuazione Bash

mi rendo conto che si può fare questo:

echo "continuation \ 
lines" 
>continuation lines 

Tuttavia, se si è rientrato codice, non funziona così bene:

echo "continuation \ 
    lines" 
>continuation  lines 
+4

Guida di stile Bash Shell di Google [consiglia "qui" i documenti] (https://google.github.io/styleguide/shell.xml # Line_Length_and_Long_Strings) per "Se devi scrivere stringhe che superano gli 80 caratteri". Vedi [@ tripleee's answer] (http://stackoverflow.com/questions/7316107/bash-continuation-lines/7316685#7316685). –

risposta

113

Questo è ciò che può essere utile

$  echo "continuation"\ 
>  "lines" 
continuation lines 

Se questo crea due argomenti da echo e ne vuoi uno solo, esaminiamo la concatenazione di stringhe. In bash, mettendo due stringhe una accanto all'altra concatenate:

$ echo "continuation""lines" 
continuationlines 

Quindi una riga di continuazione senza un trattino è un modo per rompere una stringa:

$ echo "continuation"\ 
> "lines" 
continuationlines 

Ma quando viene utilizzato un trattino :

$  echo "continuation"\ 
>  "lines" 
continuation lines 

Si ottengono due argomenti perché non si tratta più di una concatenazione.

Se volete una singola stringa che attraversa le linee, mentre il rientro ma non ottenere tutti quegli spazi, un approccio che si può provare è di abbandonare la linea di continuazione e sull'uso di variabili:

$ a="continuation" 
$ b="lines" 
$ echo $a$b 
continuationlines 

Questo vi permetterà di avere un codice rientrato in modo pulito a scapito di variabili aggiuntive. Se rendi le variabili locali non dovrebbe essere troppo cattivo.

+0

Grazie per l'aiuto, ma mentre questo rimuove gli spazi, ora sono parametri separati (Bash interpreta gli spazi sulla seconda riga come separatore di parametri) e ora vengono stampati correttamente solo a causa del comando echo. –

+1

Oh, ti piacerebbe una singola stringa (bash) su tutte le linee! Ora vedo. –

+3

Soluzione con una variabile: 's =" numero di stringa 1 " s + =" numero di stringa 2 " s + =" numero di stringa 3 " echo" $ s "' –

25

Qui i documenti con il terminatore <<-HERE funzionano bene per le stringhe di testo multiriga rientrate. Rimuoverà tutte le schede iniziali dal documento qui.

cat <<-____HERE 
    continuation 
    lines 
____HERE 

Vedi anche http://ss64.com/bash/syntax-here.html

Se è necessario per preservare alcuni, ma non tutti, gli spazi restanti, si potrebbe usare qualcosa llke

sed 's/^ //' <<____HERE 
    This has four leading spaces. 
    Two of them will be removed by sed. 
____HERE 
-1

Questo probabilmente in realtà non rispondere alla tua domanda, ma lo potresti trovare comunque utile.

Il primo comando crea lo script visualizzato dal secondo comando.

Il terzo comando rende eseguibile lo script.

Il quarto comando fornisce un esempio di utilizzo.

[email protected]:~/tmp/so$ echo $'#!/usr/bin/env python\nimport textwrap, sys\n\ndef bash_dedent(text):\n """Dedent all but the first line in the passed `text`."""\n try:\n  first, rest = text.split("\\n", 1)\n  return "\\n".join([first, textwrap.dedent(rest)])\n except ValueError:\n  return text # single-line string\n\nprint bash_dedent(sys.argv[1])' > bash_dedent 
[email protected]:~/tmp/so$ cat bash_dedent 
#!/usr/bin/env python 
import textwrap, sys 

def bash_dedent(text): 
    """Dedent all but the first line in the passed `text`.""" 
    try: 
     first, rest = text.split("\n", 1) 
     return "\n".join([first, textwrap.dedent(rest)]) 
    except ValueError: 
     return text # single-line string 

print bash_dedent(sys.argv[1]) 
[email protected]:~/tmp/so$ chmod a+x bash_dedent 
[email protected]:~/tmp/so$ echo "$(./bash_dedent "first line 
>  second line 
>  third line")" 
first line 
second line 
third line 

Si noti che se si vuole veramente utilizzare questo script, ha più senso per spostare lo script eseguibile in ~/bin in modo che sia nel tuo percorso.

Controllare il riferimento Python per i dettagli su come funziona textwrap.dedent.

Se l'utilizzo di $'...' o "$(...)" ti confonde, fai un'altra domanda (una per costrutto) se non ce ne è già una. Potrebbe essere utile fornire un link alla domanda che trovi/chiedi in modo che altre persone abbiano un riferimento collegato.

+5

Ben intenzionato- e possibilmente anche utile- anche se questo potrebbe essere, l'OP ha chiesto consigli sulla sintassi bash di base e gli hai fornito una definizione di funzione python che utilizza paradigmi OO, controllo del flusso eccezionale e importazioni. Inoltre, hai chiamato un eseguibile come parte di un'interpolazione di stringa - qualcosa che una persona che ha fatto questo tipo di domanda non avrebbe sicuramente visto in bash. –

2

Mi sono imbattuto in una situazione in cui dovevo inviare un messaggio lungo come parte di un argomento di comando e dovevo rispettare la limitazione della lunghezza della linea. I comandi simile a questa:

somecommand --message="I am a long message" args 

Il modo in cui ho risolto questo è quello di spostare il messaggio come documento qui (come @tripleee suggerito). Ma un documento diventa qui uno stdin, quindi ha bisogno di essere letto nuovamente, sono andato con l'approccio seguito:

message=$(
    tr "\n" " " <<- END 
     This is a 
     long message 
END 
) 
somecommand --message="$message" args 

Questo ha il vantaggio che $message può essere utilizzato esattamente come la stringa costante senza spazi extra o interruzioni di riga.

Si noti che le righe di messaggio attuali sopra sono precedute dal prefisso con un carattere tab, che viene rimosso dal documento stesso (a causa dell'uso di <<-). Ci sono ancora interruzioni di riga alla fine, che vengono poi sostituite da dd con spazi.

Si noti inoltre che se non si rimuovono i ritorni a capo, essi appariranno così come sono quando "$message" viene espanso. In alcuni casi, è possibile risolvere il problema rimuovendo le doppie virgolette intorno a $message, ma il messaggio non sarà più un singolo argomento.

-1

However, if you have indented code, it doesn't work out so well:

echo "continuation \ 
    lines" 
>continuation  lines 

Prova con virgolette singole e concatenando le stringhe:

echo 'continuation' \ 
    'lines' 
>continuation lines 

Nota: la concatenazione include uno spazio bianco.

+1

Funziona con gli argomenti echo e stringa, ma non funziona con altre cose, come l'assegnazione delle variabili. Sebbene la domanda non riguardasse le variabili, l'uso dell'eco era solo un esempio. Invece di echo 'se tu avessi' x = ', avresti ottenuto l'errore:' lines: command not found'. –

2

È possibile utilizzare bash arrays

$ str_array=("continuation" 
      "lines") 

poi

$ echo "${str_array[*]}" 
continuation lines 

c'è uno spazio in più, perché (dopo il manuale di bash):

If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS variable

Così impostato IFS='' per sbarazzarsi di spazio extra

$ IFS='' 
$ echo "${str_array[*]}" 
continuationlines 
0

Si potrebbe semplicemente separarlo con newline (senza usare il backslash) come richiesto all'interno dell'indentazione come segue e solo strip di nuove linee.

Esempio:

echo "continuation 
of 
lines" | tr '\n' ' ' 

Oppure, se si tratta di un a capo di definizione variabile ottiene automaticamente convertiti in spazi. Quindi, striscia di spazi aggiuntivi solo se applicabile.

x="continuation 
of multiple 
lines" 
y="red|blue| 
green|yellow" 

echo $x # This will do as the converted space actually is meaningful 
echo $y | tr -d ' ' # Stripping of space may be preferable in this case 
Problemi correlati