Bash
Orddelning
Sök…
Syntax
- Ställ IFS till ny linje: IFS = $ '\ n'
- Ställ IFS till nollsträng: IFS =
- Ställ IFS till / karaktär: IFS = /
parametrar
Parameter | detaljer |
---|---|
IFS | Intern fältavskiljare |
-x | Skriv ut kommandon och deras argument när de körs (Shell-alternativ) |
Anmärkningar
- Orddelning utförs inte under uppdrag t.ex.
newvar=$var
- Orddelning utförs inte i
[[ ... ]]
-konstruktionen - Använd dubbla citat på variabler för att förhindra att orddelning sker
Dela med IFS
För att vara mer tydlig, låt oss skapa ett skript med namnet showarg
:
#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo
Låt oss nu se skillnaderna:
$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
delas upp i 4 args.IFS
är vita mellanslagstecken och således skedde orddelning i mellanslag
$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>
I ovanstående orddelning inträffade inte eftersom
IFS
tecken inte hittades.
Låt oss nu ställa in IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
delar in sig i fyra argument, inte ett enda argument.
Vad, när och varför?
När skalet utför parameterutvidgning , kommandosubstitution , variabel eller aritmetisk expansion , söker det efter ordgränser i resultatet. Om någon ordgräns hittas, delas resultatet upp i flera ord i den positionen. Ordsgränsen definieras av en skalvariabel IFS
(Internal Field Separator). Standardvärdet för IFS är utrymme, flik och ny linje, dvs orddelning kommer att inträffa på dessa tre vitrumstecken om de inte förhindras uttryckligen.
set -x
var='I am
a
multiline string'
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
I exemplet ovan är detta hur fun
körs:
fun I am a multiline string
$var
delas upp i 5 args, baraI
,am
ocha
kommer att skrivas ut.
IFS & orddelning
Se vad, när och varför om du inte vet om IFS-anslutningen till orddelning
låt oss ställa in IFS till mellanslagstecken:
set -x
var='I am
a
multiline string'
IFS=' '
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
Denna tidsorddelning fungerar bara på mellanslag. Den fun
funktionen kommer att köras så här:
fun I 'am
a
multiline' string
$var
delas upp i 3 args.I
,am\na\nmultiline
ochstring
kommer att skrivas ut
Låt oss ställa IFS till ny linje:
IFS=$'\n'
...
Nu kommer det fun
att utföras som:
fun 'I am' a 'multiline string'
$var
delas upp i 3 args.I am
,a
,multiline string
kommer att skrivas ut
Låt oss se vad som händer om vi ställer IFS till nullsträng:
IFS=
...
Den här gången utförs det fun
:
fun 'I am
a
multiline string'
$var
är inte delad, dvs det förblev en enda arg.
Du kan förhindra orddelning genom att ställa IFS till nollsträng
Ett generellt sätt att förhindra orddelning är att använda dubbelcitationstecken:
fun "$var"
kommer att förhindra att orddelning sker i alla fall som diskuterats ovan, dvs fun
kommer att köras med bara ett argument.
Dåliga effekter av orddelning
$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = $a ]
tolkades som[ I am a string with spaces = I am a string with spaces ]
.[
ärtest
för vilketI am a string with spaces
är inte ett enda argument, snarare är det 6 argument !!
$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = something ]
tolkades som[ I am a string with spaces = something ]
$ [ $(grep . file) = 'something' ]
bash: [: too many arguments
grep
kommandot returnerar en multiline sträng med mellanslag, så du kan bara tänka dig hur många argument som finns ...: D
Se vad, när och varför för grunderna.
Användbarhet vid orddelning
Det finns några fall där orddelning kan vara användbar:
Fylla upp matris:
arr=($(grep -o '[0-9]\+' file))
Detta kommer att fylla
arr
med alla numeriska värden som finns i filen
Looping genom rymdseparerade ord:
words='foo bar baz'
for w in $words;do
echo "W: $w"
done
Produktion:
W: foo
W: bar
W: baz
Passera utrymme separerade parametrar som inte innehåller vita mellanslag:
packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs
eller
packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs
Detta kommer att installera paketen. Om du dubblar offert på
$packs
kommer det att kasta ett fel.
Unquoetd
$packs
skickar alla utrymme separerade paketnamn som argument tillapt-get
, medan de citerar kommer det att skicka$packs
strängen som ett enda argument och sedan kommerapt-get
att försöka installera ett paket med namnetapache2 php php-mbstring php-mysql
(för den första) som uppenbarligen inte finns
Se vad, när och varför för grunderna.
Delning med separatorändringar
Vi kan bara göra en enkel byte av separatorer från rymd till ny linje, enligt följande exempel.
echo $sentence | tr " " "\n"
Den delar upp värdet på den variabla sentence
och visar den rad för rad respektive.