it-swarm.com.de

Mehrzeilige Zeichenfolge mit zusätzlichem Platz (eingedrückter Einzug)

Ich möchte einige vordefinierte Texte in eine Datei mit folgendem schreiben:

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

echo -e $text > filename

Ich erwarte so etwas:

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

Aber habe das bekommen:

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

Ich bin sicher, dass nach jedem \n kein Platz vorhanden ist, aber wie kommt der zusätzliche Platz heraus?

270
cizixs

Heredoc klingt für diesen Zweck bequemer. Es wird verwendet, um mehrere Befehle an ein Befehlsinterpreterprogramm wie ex oder cat zu senden.

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

Die Zeichenfolge nach "<<" gibt an, wo Sie aufhören müssen.

Um diese Zeilen an eine Datei zu senden, verwenden Sie:

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

Sie können diese Zeilen auch in einer Variablen speichern:

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

Dadurch werden die Zeilen in der Variablen VAR gespeichert.

Denken Sie beim Drucken an die Anführungszeichen um die Variable, ansonsten werden die Zeilenumbrüche nicht angezeigt.

echo "$VAR"

Besser noch, Sie können die Einrückung verwenden, um den Code stärker hervorzuheben. Fügen Sie diesmal ein "-" nach "<<" ein, um die Anzeige der Registerkarten zu verhindern.

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

Dann müssen Sie jedoch Tabulatoren und keine Leerzeichen für die Einrückung in Ihrem Code verwenden.

463
new-kid

Wenn Sie versuchen, den String in eine Variable zu bekommen, ist eine andere einfache Möglichkeit etwa die folgende:

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

Wenn Sie Ihre Zeichenfolge mit Tabulatoren einrücken (d. H. '\ T'), wird die Einrückung entfernt. Wenn Sie mit Leerzeichen einrücken, wird der Einzug dort belassen.

HINWEIS: Es ist ist signifikant, dass sich die letzte schließende Klammer in einer anderen Zeile befindet. Der END-Text muss in einer eigenen Zeile stehen.

104
Andrew Miner

echo fügt Leerzeichen zwischen den übergebenen Argumenten hinzu. $text unterliegt einer Variablenerweiterung und Word-Aufteilung, daher entspricht Ihr echo-Befehl:

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

Sie können sehen, dass vor "this" ein Leerzeichen hinzugefügt wird. Sie können entweder die Zeilenumbrüche entfernen und $text zitieren, um die Zeilenumbrüche zu erhalten:

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

echo "$text" > filename

Oder Sie könnten printf verwenden, das robuster und portabler ist als echo:

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

In bash, das die Klammererweiterung unterstützt, können Sie sogar Folgendes tun:

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

in einem Bash-Skript funktioniert Folgendes:

#!/bin/sh

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

Alternative:

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

cat Dateiname gibt an:

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

Ich habe mehr Lösungen gefunden, seit ich jede Zeile richtig eingerückt haben wollte:

  1. Sie können echo verwenden:

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

    Es funktioniert nicht, wenn Sie "\n" direkt vor \ an das Ende einer Zeile setzen.

  2. Alternativ können Sie printf verwenden, um die Portabilität zu verbessern (ich hatte mit echo eine Menge Probleme):

    printf '%s\n' \
        "this is line one"   \
        "this is line two"   \
        "this is line three" \
        > filename
    
  3. Eine weitere Lösung könnte sein:

    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
    

    oder 

    text=''
    text+="this is line one\n"
    text+="this is line two\n"
    text+="this is line three\n"
    printf "%b" "$text" > filename
    
  4. Eine andere Lösung wird durch Mischen von printf und sed erreicht. 

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

    Es ist nicht einfach, Code, der auf diese Weise formatiert ist, umzuwandeln, da die Einrückungsebene hart in den Code kodiert wird.

  5. Es ist möglich, eine Hilfsfunktion und einige Variationen für die Substitution zu verwenden:

    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

es wird funktionieren, wenn Sie es wie folgt setzen:

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

Das Folgende ist meine bevorzugte Methode, um einer Variablen eine mehrzeilige Zeichenfolge zuzuweisen (ich denke, es sieht nett aus).

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

String1
String2
String3
...
StringN
_______________________________________________________________________________

Die Anzahl der Unterstriche ist in beiden Fällen gleich (hier 80).

0