risposta-alla-domanda-sullo-sviluppo-web-bd.com

Stringa multilinea con spazio aggiuntivo (rientranza conservata)

Voglio scrivere alcuni testi predefiniti in un file con il seguente:

text="this is line one\n
this is line two\n
this is line three"

echo -e $text > filename

Mi aspetto qualcosa del genere:

this is line one
this is line two
this is line three

Ma capito:

this is line one
 this is line two
 this is line three

Sono sicuro che non ci sia spazio dopo ogni \n, ma come viene fuori lo spazio extra?

270
cizixs

Heredoc sembra più conveniente per questo scopo. È usato per inviare comandi multipli a un programma interprete di comandi come ex o cat

cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage

La stringa dopo "<<" indica dove fermarsi.

Per inviare queste righe a un file, utilizzare:

cat > $FILE <<- EOM
Line 1.
Line 2.
EOM

Puoi anche memorizzare queste righe su una variabile:

read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM

Memorizza le righe alla variabile denominata VAR.

Durante la stampa, ricorda le virgolette attorno alla variabile altrimenti non vedrai i caratteri di nuova riga.

echo "$VAR"

Ancora meglio, puoi usare il rientro per farlo risaltare maggiormente nel tuo codice. Questa volta basta aggiungere un "-" dopo "<<" per interrompere la visualizzazione delle schede.

read -r -d '' VAR <<- EOM
    This is line 1.
    This is line 2.
    Line 3.
EOM

Ma poi devi usare tabulazioni, non spazi, per il rientro nel tuo codice.

463
new-kid

Se stai cercando di ottenere la stringa in una variabile, un altro modo semplice è qualcosa del genere:

USAGE=$(cat <<-END
    This is line one.
    This is line two.
    This is line three.
END
)

Se rientri la stringa con le schede (ad es., "\ T"), la rientranza verrà eliminata. Se rientri con spazi, verrà lasciato il rientro.

NOTA: It is significativo che l'ultima parentesi chiusa si trova su un'altra riga. Il testo END deve apparire su una riga da solo.

104
Andrew Miner

echo aggiunge spazi tra gli argomenti passati ad esso. $text è soggetto a espansione variabile e suddivisione in parole, quindi il comando echo equivale a:

echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n"  ...

Puoi vedere che uno spazio verrà aggiunto prima di "questo". Puoi rimuovere i caratteri di nuova riga e citare $text per preservare le nuove righe:

text="this is line one
this is line two
this is line three"

echo "$text" > filename

Oppure puoi usare printf, che è più robusto e portatile di echo:

printf "%s\n" "this is line one" "this is line two" "this is line three" > filename

In bash, che supporta l'espansione delle parentesi graffe, si potrebbe anche fare:

printf "%s\n" "this is line "{one,two,three} > filename
63
Josh Jolly

in uno script bash i seguenti lavori:

#!/bin/sh

text="this is line one\nthis is line two\nthis is line three"
echo $text > filename

in alternativa:

text="this is line one
this is line two
this is line three"
echo "$text" > filename

nome del file cat dà:

this is line one
this is line two
this is line three
32
Chris Maes

Ho trovato più soluzioni poiché volevo che ogni riga fosse rientrata correttamente:

  1. Puoi usare echo:

    echo    "this is line one"   \
        "\n""this is line two"   \
        "\n""this is line three" \
        > filename
    

    Non funziona se si inserisce "\n" appena prima di \ alla fine di una riga.

  2. In alternativa, puoi usare printf per una migliore portabilità (mi è capitato di avere molti problemi con echo):

    printf '%s\n' \
        "this is line one"   \
        "this is line two"   \
        "this is line three" \
        > filename
    
  3. Un'altra soluzione potrebbe essere:

    text=''
    text="${text}this is line one\n"
    text="${text}this is line two\n"
    text="${text}this is line three\n"
    printf "%b" "$text" > filename
    

    text=''
    text+="this is line one\n"
    text+="this is line two\n"
    text+="this is line three\n"
    printf "%b" "$text" > filename
    
  4. Un'altra soluzione è ottenuta mescolando printf e sed

    if something
    then
        printf '%s' '
        this is line one
        this is line two
        this is line three
        ' | sed '1d;$d;s/^    //g'
    fi
    

    Non è facile effettuare il refactoring del codice formattato in questo modo mentre si codifica il codice di indentazione nel codice.

  5. È possibile utilizzare una funzione di supporto e alcuni trucchi di sostituzione variabili:

    unset text
    _() { text="${text}${text+
    }${*}"; }
    # That's an empty line which demonstrates the reasoning behind 
    # the usage of "+" instead of ":+" in the variable substitution 
    # above.
    _ ""
    _ "this is line one"
    _ "this is line two"
    _ "this is line three"
    unset -f _
    printf '%s' "$text"
    
24

funzionerà se lo metti come di seguito:

AA='first line
\nsecond line 
\nthird line'
echo $AA
output:
first line
second line
third line
1
luk

Quello che segue è il mio modo preferito per assegnare una stringa multi-linea a una variabile (penso che appaia carina).

read -r -d '' my_variable << \
_______________________________________________________________________________

String1
String2
String3
...
StringN
_______________________________________________________________________________

Il numero di caratteri di sottolineatura è lo stesso (qui 80) in entrambi i casi.

0