Ik wil een aantal vooraf gedefinieerde teksten naar een bestand schrijven met het volgende:
text="this is line one\n
this is line two\n
this is line three"
echo -e $text > filename
Ik verwacht zoiets als dit:
this is line one
this is line two
this is line three
Maar ik heb dit:
this is line one
this is line two
this is line three
Ik weet zeker dat er geen spatie is na elke \n
, maar hoe komt de extra spatie eruit?
Antwoord 1, autoriteit 100%
Heredoc klinkt handiger voor dit doel. Het wordt gebruikt om meerdere commando’s te sturen naar een commando-interpreterprogramma zoals exof cat
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
De tekenreeks na <<
geeft aan waar te stoppen.
Om deze regels naar een bestand te sturen, gebruik je:
cat > $FILE <<- EOM
Line 1.
Line 2.
EOM
U kunt deze regels ook opslaan in een variabele:
read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM
Hiermee worden de regels opgeslagen in de variabele met de naam VAR
.
Onthoud bij het afdrukken de aanhalingstekens rond de variabele, anders ziet u de tekens van de nieuwe regel niet.
echo "$VAR"
Nog beter, je kunt inspringen gebruiken om het meer op te laten vallen in je code. Voeg deze keer gewoon een -
toe na <<
om te voorkomen dat de tabbladen verschijnen.
read -r -d '' VAR <<- EOM
This is line 1.
This is line 2.
Line 3.
EOM
Maar dan moet je tabs gebruiken, geen spaties, voor inspringing in je code.
Antwoord 2, autoriteit 30%
Als je de string in een variabele probeert te krijgen, is een andere gemakkelijke manier zoiets als dit:
USAGE=$(cat <<-END
This is line one.
This is line two.
This is line three.
END
)
Als u uw tekenreeks inspringt met tabs (d.w.z. ‘\t’), wordt de inspringing verwijderd. Als u inspringt met spaties, blijft de inspringing behouden.
OPMERKING: Het issignificant dat het laatste haakje sluiten op een andere regel staat. De tekst END
moet alleen op een regel verschijnen.
Antwoord 3, autoriteit 12%
echo
voegt spaties toe tussen de argumenten die eraan worden doorgegeven. $text
is onderhevig aan variabele uitbreiding en woordsplitsing, dus uw echo
-opdracht is gelijk aan:
echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n" ...
Je kunt zien dat er een spatie wordt toegevoegd voor “dit”. U kunt ofwel de tekens van de nieuwe regel verwijderen en $text
citeren om de nieuwe regels te behouden:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
Of je zou printf
kunnen gebruiken, wat robuuster en draagbaarder is dan echo
:
printf "%s\n" "this is line one" "this is line two" "this is line three" > filename
In bash
, die brace-expansie ondersteunt, kunt u zelfs doen:
printf "%s\n" "this is line "{one,two,three} > filename
Antwoord 4, Autoriteit 7%
In een bash-script De volgende werken:
#!/bin/sh
text="this is line one\nthis is line two\nthis is line three"
echo -e $text > filename
alternatief:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
Cat FileName geeft:
this is line one
this is line two
this is line three
Antwoord 5, Autoriteit 5%
Ik heb meer oplossingen gevonden sinds ik elke regel op de juiste manier heb ingesprongen:
-
U kunt
echo
gebruiken:echo "this is line one" \ "\n""this is line two" \ "\n""this is line three" \ > filename
Het werkt niet als u
"\n"
vóór\
aan het einde van een regel plaatst. -
U kunt ook gebruik maken van
printf
voor een betere draagbaarheid (ik heb toevallig veel problemen metecho
):printf '%s\n' \ "this is line one" \ "this is line two" \ "this is line three" \ > filename
-
Nog een andere oplossing kan zijn:
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
of
text='' text+="this is line one\n" text+="this is line two\n" text+="this is line three\n" printf "%b" "$text" > filename
-
Een andere oplossing wordt bereikt door
printf
ensed
te mengen.if something then printf '%s' ' this is line one this is line two this is line three ' | sed '1d;$d;s/^ //g' fi
Het is niet eenvoudig om code die op deze manier is opgemaakt te refactoreren terwijl u het inspringingsniveau hardcodeert in de code.
-
Het is mogelijk om een helperfunctie te gebruiken en enkele trucjes voor het vervangen van variabelen:
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"
Antwoord 6
De volgende manier is mijn voorkeur om een string met meerdere regels aan een variabele toe te wijzen (ik vind het er mooi uitzien).
read -r -d '' my_variable << \
_______________________________________________________________________________
String1
String2
String3
...
StringN
_______________________________________________________________________________
Het aantal underscores is in beide gevallen hetzelfde (hier 80).
Antwoord 7
Ik kwam horen zoeken naar dit antwoord, maar wilde het ook naar een ander commando pijpen. Het gegeven antwoord is correct, maar als iemand het wil pijpen, moet je het pijpen vóór de multi-line-tekenreeks zoals deze
echo | tee /tmp/pipetest << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
Hiermee kunt u een multi-line-tekenreeks hebben, maar ook in de stdin van een volgende opdracht plaatsen.
Antwoord 8
Het werkt als u het hieronder legt:
AA='first line
\nsecond line
\nthird line'
echo $AA
output:
first line
second line
third line
Antwoord 9
Om te vermelden een eenvoudige aaneenvoeging van één lijn omdat het soms nuttig kan zijn.
# for bash
v=" guga "$'\n'" puga "
# Just for an example.
v2="bar "$'\n'" foo "$'\n'"$v"
# Let's simplify the previous version of $v2.
n=$'\n'
v3="bar ${n} foo ${n}$v"
echo "$v3"
je krijgt zoiets
Bar foo guga puga
Alle toonaangevende en eindruimten worden voor
gecontroleerd
echo "$v3" > filename
Antwoord 10
Er zijn veel manieren om het te doen. Voor mij, de inspringende string in sed werkt mooi.
printf_strip_indent() {
printf "%s" "$1" | sed "s/^\s*//g"
}
printf_strip_indent "this is line one
this is line two
this is line three" > "file.txt"
Dit antwoord was gebaseerd op het antwoord van Mateusz Piotrowski, maar een beetje verfijnd.
Antwoord 11
Of tekst ingesprongen houden met spaties:
#!/bin/sh
sed 's/^[[:blank:]]*//' >filename <<EOF
this is line one
this is line two
this is line three
EOF
Hetzelfde maar met een variabele:
#!/bin/sh
text="$(sed 's/^[[:blank:]]*//' << whatever
this is line one
this is line two
this is line three
)"
echo "$text" > filename
😉