Hoe tekenreeksvariabelen samen te voegen in Bash

In PHP worden strings als volgt samengevoegd:

$foo = "Hello";
$foo .= " World";

Hier wordt $foo“Hallo wereld”.

Hoe wordt dit bereikt in Bash?


Antwoord 1, autoriteit 100%

foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World

In het algemeen kunt u, om twee variabelen samen te voegen, ze gewoon achter elkaar schrijven:

a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World

Antwoord 2, autoriteit 29%

Bash ondersteunt ook een +=operator zoals getoond in deze code:

A="X Y"
A+=" Z"
echo "$A"

uitvoer

X Y Z


Antwoord 3, autoriteit 24%

Bash eerst

Aangezien deze vraag specifiek voor Bashstaat, is mijn eerste deel van het antwoord zou verschillende manieren presenteren om dit goed te doen:

+=: toevoegen aan variabele

De syntaxis +=kan op verschillende manieren worden gebruikt:

Toevoegen aan string var+=...

(Omdat ik zuinig ben, zal ik slechts twee variabelen fooen agebruiken en vervolgens dezelfde opnieuw gebruiken in het hele antwoord. 😉

a=2
a+=4
echo $a
24

De syntaxis Stack Overflow-vraaggebruiken,

foo="Hello"
foo+=" World"
echo $foo
Hello World

werkt prima!

Toevoegen aan een geheel getal ((var+=...))

variabele ais een string, maar ook een geheel getal

echo $a
24
((a+=12))
echo $a
36

Toevoegen aan een array var+=(...)

Onze ais ook een array van slechts één element.

echo ${a[@]}
36
a+=(18)
echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18

Merk op dat er tussen haakjes een door spaties gescheiden arraystaat. Als u een string met spaties in uw array wilt opslaan, moet u deze omsluiten:

a+=(one word "hello world!" )
bash: !": event not found

Hmm.. dit is geen bug, maar een functie… Om te voorkomen dat bash probeert te ontwikkelen !", kunt u:

a+=(one word "hello world"! 'hello world!' $'hello world\041')
declare -p a
declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="h
ello world!" [6]="hello world!")'

printf: Reconstrueer de variabele met het ingebouwdecommando

De opdracht printfingebouwdegeeft een krachtige manier om tekenreeksen te tekenen. Aangezien dit een Bash ingebouwdis, is er een optie om een opgemaakte string naar een variabele te sturen in plaats van af te drukken op stdout:

echo ${a[@]}
36 18 one word hello world! hello world! hello world!

Er zijn zeven stringsin deze array. We zouden dus een opgemaakte string kunnen bouwen die precies zeven positionele argumenten bevat:

printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'

Of we kunnen één tekenreeks voor argumentopmaakgebruiken die wordt herhaald als er zoveel argumenten zijn ingediend…

Merk op dat onze anog steeds een array is! Alleen het eerste element is gewijzigd!

declare -p a
declare -a a='([0]="36./.18...'\''one'\'' '\''word'\'', '\''hello world!'\''=='\
''hello world!'\''=='\''hello world!'\''" [1]="18" [2]="one" [3]="word" [4]="hel
lo world!" [5]="hello world!" [6]="hello world!")'

Onder bash, wanneer u een variabelenaam opent zonder index op te geven, adresseert u altijd alleen het eerste element!

Dus om onze array met zeven velden op te halen, hoeven we alleen het eerste element opnieuw in te stellen:

a=36
declare -p a
declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="he
llo world!" [6]="hello world!")'

Eén tekenreeks voor argumentindeling met veel argumenten doorgegeven aan:

printf -v a[0] '<%s>\n' "${a[@]}"
echo "$a"
<36>
<18>
<one>
<word>
<hello world!>
<hello world!>
<hello world!>

De syntaxis Stack Overflow-vraaggebruiken:

foo="Hello"
printf -v foo "%s World" $foo
echo $foo
Hello World

Opmerking: Het gebruik van dubbele aanhalingstekenskan handig zijn voor het manipuleren van tekenreeksen die spaces, tabulationsen/of newlines

printf -v foo "%s World" "$foo"

Shell nu

Onder POSIXshell kon je geen bashismsgebruiken, dus er is geen ingebouwdeprintf.

Eigenlijk

Maar je zou gewoon kunnen doen:

foo="Hello"
foo="$foo World"
echo $foo
Hello World

Geformatteerd, met behulp van gevorkteprintf

Als je meer geavanceerde constructies wilt gebruiken, moet je een forkgebruiken (nieuw onderliggend proces dat de taak maakt en het resultaat retourneert via stdout):

foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World

Historisch gezien zou u backtickskunnen gebruiken om het resultaat van een forkop te halen:

foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World

Maar dit is niet gemakkelijk voor nesten:

foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013

met backticks moet je de binnenvorken ontwijken met backslashes:

foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013

Antwoord 4, autoriteit 3%

U kunt dit ook doen:

$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh

Antwoord 5, autoriteit 3%

bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

Zal uitvoeren

helloohaikthxbye

Dit is handig wanneer
$blaohai
leidt tot een variabele niet gevonden fout. Of als je spaties of andere speciale tekens in je strings hebt. "${foo}"ontsnapt correct aan alles wat je erin stopt.


Antwoord 6

foo="Hello "
foo="$foo World"

     


Antwoord 7

Hier is een beknopte samenvatting van waar de meeste antwoorden over gaan.

Stel dat we twee variabelen hebben en $1 is ingesteld op ‘één’:

set one two
a=hello
b=world

De onderstaande tabel legt de verschillende contexten uit waarin we de waarden van aen bkunnen combineren om een nieuwe variabele te creëren, c.

Context                               | Expression            | Result (value of c)
--------------------------------------+-----------------------+---------------------
Two variables                         | c=$a$b                | helloworld
A variable and a literal              | c=${a}_world          | hello_world
A variable and a literal              | c=$1world             | oneworld
A variable and a literal              | c=$a/world            | hello/world
A variable, a literal, with a space   | c=${a}" world"        | hello world
A more complex expression             | c="${a}_one|${b}_2"   | hello_one|world_2
Using += operator (Bash 3.1 or later) | c=$a; c+=$b           | helloworld
Append literal with +=                | c=$a; c+=" world"     | hello world

Een paar opmerkingen:

  • het plaatsen van de RHS van een opdracht tussen dubbele aanhalingstekens is over het algemeen een goede gewoonte, hoewel het in veel gevallen vrij optioneel is
  • +=is vanuit prestatieoogpunt beter als een grote string in kleine stappen wordt geconstrueerd, vooral in een lus
  • gebruik {}rond variabelenamen om hun uitbreiding ondubbelzinnig te maken (zoals in rij 2 in de bovenstaande tabel). Zoals te zien is in rijen 3 en 4, is {}niet nodig, tenzij een variabele wordt samengevoegd met een tekenreeks die begint met een teken dat een geldig eerste teken is in de naam van de shell-variabele, dat wil zeggen alfabet of onderstrepingsteken.

Zie ook:


Antwoord 8

De manier waarop ik het probleem zou oplossen is gewoon

$a$b

Bijvoorbeeld

a="Hello"
b=" World"
c=$a$b
echo "$c"

die produceert

Hello World

Als u bijvoorbeeld een tekenreeks probeert samen te voegen met een andere tekenreeks,

a="Hello"
c="$a World"

Dan echo "$c"produceert

Hello World

met een extra ruimte.

$aWorld

werkt niet, zoals u zich mag voorstellen, maar

${a}World

produceert

HelloWorld

Antwoord 9

$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop

Antwoord 10

Nog een andere aanpak …

> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.

… en toch nog een andere.

> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.

Antwoord 11

Als u iets als een onderstrepingsporen wilt toevoegen, gebruik dan Escape (\)

FILEPATH=/opt/myfile

Dit doet niet werk:

echo $FILEPATH_$DATEX

Dit werkt prima:

echo $FILEPATH\\_$DATEX

Antwoord 12

De eenvoudigste manier met aanhalingstekens:

B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"

Antwoord 13

Zelfs als de += operator nu is toegestaan, is deze in 2004 geïntroduceerd in Bash 3.1.

Elk script dat deze operator op oudere Bash-versies gebruikt, zal mislukken met een “opdracht niet gevonden”-fout als je geluk hebt, of een “syntaxisfout bijna onverwacht token”.

Voor degenen die achterwaartse compatibiliteit belangrijk vinden, blijf bij de oudere standaard Bash-aaneenschakelingsmethoden, zoals die vermeld in het gekozen antwoord:

foo="Hello"
foo="$foo World"
echo $foo
> Hello World

Antwoord 14

U kunt samenvoegen zonder de aanhalingstekens. Hier is een voorbeeld:

$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3

Deze laatste verklaring zou “OpenSystems” (zonder aanhalingstekens) afdrukken.

Dit is een voorbeeld van een Bash-script:

v1=hello
v2=world
v3="$v1       $v2"
echo $v3            # Output: hello world
echo "$v3"          # Output: hello       world

Antwoord 15

Ik gebruik liever accolades ${}om variabele in string uit te breiden:

foo="Hello"
foo="${foo} World"
echo $foo
> Hello World

Krulhaken passen bij continu tekenreeksgebruik:

foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld

Anders werkt het gebruik van foo = "$fooWorld"niet.


Antwoord 16

Als u probeert een string te splitsenin meerdere regels, kunt u een backslash gebruiken:

$ a="hello\
> world"
$ echo $a
helloworld

Met één spatie ertussen:

$ a="hello \
> world"
$ echo $a
hello world

Deze voegt ook maar één spatie ertussen toe:

$ a="hello \
> world"
$ echo $a
hello world

Antwoord 17

Veiligere manier:

a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD

Tekenreeksen die spaties bevatten, kunnen onderdeel worden van de opdracht. Gebruik “$XXX” en “${XXX}” om deze fouten te voorkomen.

Kijk ook eens naar een ander antwoord over +=


Antwoord 18

Er is één specifiek geval waar u op moet letten:

user=daniel
cat > output.file << EOF
"$user"san
EOF

Geef "daniel"sanweer, en niet danielsan, zoals je misschien had gewild.
In dit geval moet u in plaats daarvan doen:

user=daniel
cat > output.file << EOF
${user}san
EOF

Antwoord 19

Ondanks de speciale operator, +=, is er voor aaneenschakeling een eenvoudigere manier:

foo='Hello'
foo=$foo' World'
echo $foo

Dubbele aanhalingstekens kosten extra rekentijd voor de interpretatie van variabelen binnenin. Vermijd het indien mogelijk.


Antwoord 20

a="Hello,"
a=$a" World!"
echo $a

Dit is hoe je aaneenschakelen twee strings.


Antwoord 21

Als het als uw voorbeeld van het toevoegen " World"om de oorspronkelijke tekenreeks, dan kan het zijn:

#!/bin/bash
foo="Hello"
foo=$foo" World"
echo $foo

De uitvoer:

Hello World

Antwoord 22

var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3

Antwoord 23

Er zijn zorgen geuit over de prestaties, maar er worden geen gegevens aangeboden. Laat me een eenvoudige test.

(NB:. dateMacOS niet bieden nanoseconden, dus dit moet worden gedaan op Linux)

ik heb gemaakt append_test.sh op GitHub met de inhoud:

#!/bin/bash -e
output(){
    ptime=$ctime;
    ctime=$(date +%s.%N);
    delta=$(bc <<<"$ctime - $ptime");
    printf "%2s. %16s chars  time: %s  delta: %s\n" $n "$(bc <<<"10*(2^$n)")" $ctime $delta;
}
method1(){
    echo 'Method: a="$a$a"'
    for n in {1..32}; do a="$a$a"; output; done
}
method2(){
    echo 'Method: a+="$a"'
    for n in {1..32}; do a+="$a";  output; done
}
ctime=0; a="0123456789"; time method$1

Test 1:

$ ./append_test.sh 1
Method: a="$a$a"
 1.               20 chars  time: 1513640431.861671143  delta: 1513640431.861671143
 2.               40 chars  time: 1513640431.865036344  delta: .003365201
 3.               80 chars  time: 1513640431.868200952  delta: .003164608
 4.              160 chars  time: 1513640431.871273553  delta: .003072601
 5.              320 chars  time: 1513640431.874358253  delta: .003084700
 6.              640 chars  time: 1513640431.877454625  delta: .003096372
 7.             1280 chars  time: 1513640431.880551786  delta: .003097161
 8.             2560 chars  time: 1513640431.883652169  delta: .003100383
 9.             5120 chars  time: 1513640431.886777451  delta: .003125282
10.            10240 chars  time: 1513640431.890066444  delta: .003288993
11.            20480 chars  time: 1513640431.893488326  delta: .003421882
12.            40960 chars  time: 1513640431.897273327  delta: .003785001
13.            81920 chars  time: 1513640431.901740563  delta: .004467236
14.           163840 chars  time: 1513640431.907592388  delta: .005851825
15.           327680 chars  time: 1513640431.916233664  delta: .008641276
16.           655360 chars  time: 1513640431.930577599  delta: .014343935
17.          1310720 chars  time: 1513640431.954343112  delta: .023765513
18.          2621440 chars  time: 1513640431.999438581  delta: .045095469
19.          5242880 chars  time: 1513640432.086792464  delta: .087353883
20.         10485760 chars  time: 1513640432.278492932  delta: .191700468
21.         20971520 chars  time: 1513640432.672274631  delta: .393781699
22.         41943040 chars  time: 1513640433.456406517  delta: .784131886
23.         83886080 chars  time: 1513640435.012385162  delta: 1.555978645
24.        167772160 chars  time: 1513640438.103865613  delta: 3.091480451
25.        335544320 chars  time: 1513640444.267009677  delta: 6.163144064
./append_test.sh: fork: Cannot allocate memory

Test 2:

$ ./append_test.sh 2
Method: a+="$a"
 1.               20 chars  time: 1513640473.460480052  delta: 1513640473.460480052
 2.               40 chars  time: 1513640473.463738638  delta: .003258586
 3.               80 chars  time: 1513640473.466868613  delta: .003129975
 4.              160 chars  time: 1513640473.469948300  delta: .003079687
 5.              320 chars  time: 1513640473.473001255  delta: .003052955
 6.              640 chars  time: 1513640473.476086165  delta: .003084910
 7.             1280 chars  time: 1513640473.479196664  delta: .003110499
 8.             2560 chars  time: 1513640473.482355769  delta: .003159105
 9.             5120 chars  time: 1513640473.485495401  delta: .003139632
10.            10240 chars  time: 1513640473.488655040  delta: .003159639
11.            20480 chars  time: 1513640473.491946159  delta: .003291119
12.            40960 chars  time: 1513640473.495354094  delta: .003407935
13.            81920 chars  time: 1513640473.499138230  delta: .003784136
14.           163840 chars  time: 1513640473.503646917  delta: .004508687
15.           327680 chars  time: 1513640473.509647651  delta: .006000734
16.           655360 chars  time: 1513640473.518517787  delta: .008870136
17.          1310720 chars  time: 1513640473.533228130  delta: .014710343
18.          2621440 chars  time: 1513640473.560111613  delta: .026883483
19.          5242880 chars  time: 1513640473.606959569  delta: .046847956
20.         10485760 chars  time: 1513640473.699051712  delta: .092092143
21.         20971520 chars  time: 1513640473.898097661  delta: .199045949
22.         41943040 chars  time: 1513640474.299620758  delta: .401523097
23.         83886080 chars  time: 1513640475.092311556  delta: .792690798
24.        167772160 chars  time: 1513640476.660698221  delta: 1.568386665
25.        335544320 chars  time: 1513640479.776806227  delta: 3.116108006
./append_test.sh: fork: Cannot allocate memory

De fouten geven aan dat mijn Bash maximaal 335.54432 MBhad voordat het crashte. U kunt de codewijzigen van het verdubbelen van de gegevens naar het toevoegen van een constante om een meer gedetailleerde grafiek te krijgen en faalpunt. Maar ik denk dat dit je genoeg informatie moet geven om te beslissen of het je iets kan schelen. Persoonlijk doe ik dat niet onder de 100 MB. Uw kilometerstand kan variëren.


Antwoord 24

Ik wilde een string maken van een lijst. Ik kon daar geen antwoord op vinden, dus post ik het hier. Dit is wat ik deed:

list=(1 2 3 4 5)
string=''
for elm in "${list[@]}"; do
    string="${string} ${elm}"
done
echo ${string}

en dan krijg ik de volgende uitvoer:

1 2 3 4 5

Antwoord 25

Merk op dat dit niet werkt

foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar

omdat het $foo lijkt te laten vallen en je achterlaat met:

PREFIX_WORLD

maar dit zal werken:

foobar=PREFIX_"$foo"_"$bar"

en je de juiste output geven:

PREFIX_HELLO_WORLD


Antwoord 26

Hier is die van AWK:

$ foo="Hello"
$ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
$ echo $foo
Hello World

Antwoord 27

Ik doe het op deze manier wanneer het mij uitkomt: gebruik een inline commando!

echo "The current time is `date`"
echo "Current User: `echo $USER`"

Antwoord 28

Naar mijn mening is de eenvoudigste manier om twee strings samen te voegen, door een functie te schrijven die dit voor u doet en die functie vervolgens te gebruiken.

function concat ()
{
    prefix=$1
    suffix=$2
    echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar   # Superman
alien=$(concat $foo $bar)
echo $alien        # Superman

Antwoord 29

Variabelen en arrays (geïndexeerd of associatief*) in bash zijn standaard altijd strings, maar je kunt vlaggen gebruiken om de ingebouwde declarete gebruiken, om ze attributen te geven zoals “integer” (-i) of “referentie”** (-n), die de manier waarop ze zich gedragen veranderen.

Bash-rekenkunde accepteert ASCII-/tekenreeksnummers voor invoer, dus er zijn weinig redenen om het integer-kenmerk daadwerkelijk te gebruiken.

Variabele waarden mogen ook geen ASCII NULL(dwz 8 bit nul) bevatten, omdat er gewone null-getermineerde C-strings worden gebruikt om ze te implementeren.

* Dwz een of meer sleutel + waarde-paren.
** Referentievariabelen breiden uit naar de waarde van een andere variabele, waarvan het label is toegewezen aan de referentievariabele

Een tekenreeks toevoegen:

$ foo=Hello
$ foo+=' world!'
$ echo "$foo"
Hello world!
$ num=3
$ num+=4
echo "$num"
34 # Appended string (not a sum)

Een van de weinige redenen om het integer-attribuut te gebruiken, is dat het het gedrag van de +=toewijzingsoperator wijzigen:

$ declare -i num=3
$ num+=4
echo "$num"
7 # Sum

Merk op dat dit niet werkt voor -=, /=, enz. Tenzij u het binnen rekenkundige doet ((( ))en $(( ))), waar cijfers al hetzelfde zijn behandeld met of zonder het attribuut van de integer. Zie de sectie “Rekenkundige evaluatie” van man bashvoor een volledige lijst van die exploitanten, die hetzelfde zijn als voor c.

De +=Opdrachtoperator kan ook worden gebruikt om nieuwe elementen toe te voegen aan een geïndexeerde array (aka “lijst”):

$ foo=(one)
$ foo+=(two)
$ printf 'Separate element: %s\n' "${foo[@]}"
Separate element: one
Separate element: two

Nog een gemeenschappelijke manier om dit te doen is om een ​​teller te gebruiken:

$ foo[c++]=one
$ foo[c++]=two

Posix Shells DO Niet Gebruik de +=toewijzingsoperator om strings toe te voegen, dus u moet het zo doen:

$ foo=Hello
$ foo="$foo world!"
$ echo "$foo"
Hello world!

Dit is prima in bashook, dus het kan worden beschouwd als een meer draagbare syntaxis.


ANTWOORD 30

Ik vind het leuk om een ​​snelle functie te maken.

#! /bin/sh -f
function combo() {
    echo $@
}
echo $(combo 'foo''bar')

Nog een andere manier om een ​​kat te vullen. Deze keer met functies: D

Other episodes