Bash
Bash Parameter Uitbreiding
Zoeken…
Invoering
Het teken $
introduceert parameteruitbreiding, opdrachtvervanging of rekenkundige uitbreiding. De uit te breiden parameternaam of het symbool kan tussen accolades worden geplaatst, die optioneel zijn, maar dienen om de uit te breiden variabele te beschermen tegen tekens die er direct op volgen en die kunnen worden geïnterpreteerd als onderdeel van de naam.
Lees meer in de Bash User Manual .
Syntaxis
- $ {parameter: offset} # Substring beginnend bij offset
- $ {parameter: offset: length} # Substring van lengte "lengte" beginnend bij offset
- $ {# parameter} # Lengte van de parameter
- $ {parameter / pattern / string} # Vervang het eerste exemplaar van patroon door string
- $ {parameter // pattern / string} # Vervang alle exemplaren van patroon door string
- $ {parameter / # pattern / string} # Vervang patroon door string als het patroon aan het begin staat
- $ {parameter /% pattern / string} # Vervang patroon door string als het patroon aan het einde is
- $ {parameter # pattern} # Verwijder de kortste overeenkomst van het patroon uit het begin van de parameter
- $ {parameter ## pattern} # Verwijder de langste overeenkomst van het patroon uit het begin van de parameter
- $ {parameter% pattern} # Verwijder de kortste overeenkomst van patroon aan het einde van de parameter
- $ {parameter %% pattern} # Verwijder de langste overeenkomst van het patroon aan het einde van de parameter
- $ {parameter: -word} # Uitbreiden tot word als parameter niet ingesteld / ongedefinieerd
- $ {parameter: = word} # Uitbreiden tot word als parameter niet ingesteld / ongedefinieerd en parameter ingesteld
- $ {parameter: + word} # Uitbreiden tot word als parameter ingesteld / gedefinieerd
Substrings en subarrays
var='0123456789abcdef'
# Define a zero-based offset
$ printf '%s\n' "${var:3}"
3456789abcdef
# Offset and length of substring
$ printf '%s\n' "${var:3:4}"
3456
# Negative length counts from the end of the string
$ printf '%s\n' "${var:3:-5}"
3456789a
# Negative offset counts from the end
# Needs a space to avoid confusion with ${var:-6}
$ printf '%s\n' "${var: -6}"
abcdef
# Alternative: parentheses
$ printf '%s\n' "${var:(-6)}"
abcdef
# Negative offset and negative length
$ printf '%s\n' "${var: -6:-5}"
a
Dezelfde uitbreidingen zijn van toepassing als de parameter een positionele parameter of het element van een subscriptarray is :
# Set positional parameter $1
set -- 0123456789abcdef
# Define offset
$ printf '%s\n' "${1:5}"
56789abcdef
# Assign to array element
myarr[0]='0123456789abcdef'
# Define offset and length
$ printf '%s\n' "${myarr[0]:7:3}"
789
Analoge uitbreidingen zijn van toepassing op positionele parameters , waarbij offsets één zijn:
# Set positional parameters $1, $2, ...
$ set -- 1 2 3 4 5 6 7 8 9 0 a b c d e f
# Define an offset (beware $0 (not a positional parameter)
# is being considered here as well)
$ printf '%s\n' "${@:10}"
0
a
b
c
d
e
f
# Define an offset and a length
$ printf '%s\n' "${@:10:3}"
0
a
b
# No negative lengths allowed for positional parameters
$ printf '%s\n' "${@:10:-2}"
bash: -2: substring expression < 0
# Negative offset counts from the end
# Needs a space to avoid confusion with ${@:-10:2}
$ printf '%s\n' "${@: -10:2}"
7
8
# ${@:0} is $0 which is not otherwise a positional parameters or part
# of $@
$ printf '%s\n' "${@:0:2}"
/usr/bin/bash
1
Substringuitbreiding kan worden gebruikt met geïndexeerde arrays :
# Create array (zero-based indices)
$ myarr=(0 1 2 3 4 5 6 7 8 9 a b c d e f)
# Elements with index 5 and higher
$ printf '%s\n' "${myarr[@]:12}"
c
d
e
f
# 3 elements, starting with index 5
$ printf '%s\n' "${myarr[@]:5:3}"
5
6
7
# The last element of the array
$ printf '%s\n' "${myarr[@]: -1}"
f
Lengte van parameter
# Length of a string
$ var='12345'
$ echo "${#var}"
5
Merk op dat het de lengte in aantal tekens is die niet noodzakelijkerwijs hetzelfde is als het aantal bytes (zoals in UTF-8 waar de meeste tekens in meer dan één byte zijn gecodeerd), noch het aantal glyphs / graphemes (waarvan sommige combinaties van tekens), noch is het noodzakelijkerwijs hetzelfde als de weergavebreedte.
# Number of array elements
$ myarr=(1 2 3)
$ echo "${#myarr[@]}"
3
# Works for positional parameters as well
$ set -- 1 2 3 4
$ echo "${#@}"
4
# But more commonly (and portably to other shells), one would use
$ echo "$#"
4
Het geval van alfabetische tekens wijzigen
Hoofdletters
$ v="hello"
# Just the first character
$ printf '%s\n' "${v^}"
Hello
# All characters
$ printf '%s\n' "${v^^}"
HELLO
# Alternative
$ v="hello world"
$ declare -u string="$v"
$ echo "$string"
HELLO WORLD
Naar kleine letters
$ v="BYE"
# Just the first character
$ printf '%s\n' "${v,}"
bYE
# All characters
$ printf '%s\n' "${v,,}"
bye
# Alternative
$ v="HELLO WORLD"
$ declare -l string="$v"
$ echo "$string"
hello world
Schakelkast
$ v="Hello World"
# All chars
$ echo "${v~~}"
hELLO wORLD
$ echo "${v~}"
# Just the first char
hello World
Parameterindirection
Bash
indirection maakt het mogelijk om de waarde te krijgen van een variabele waarvan de naam is opgenomen in een andere variabele. Variabelen voorbeeld:
$ red="the color red"
$ green="the color green"
$ color=red
$ echo "${!color}"
the color red
$ color=green
$ echo "${!color}"
the color green
Nog enkele voorbeelden die het gebruik van indirecte expansie aantonen:
$ foo=10
$ x=foo
$ echo ${x} #Classic variable print
foo
$ foo=10
$ x=foo
$ echo ${!x} #Indirect expansion
10
Nog een voorbeeld:
$ argtester () { for (( i=1; i<="$#"; i++ )); do echo "${i}";done; }; argtester -ab -cd -ef
1 #i expanded to 1
2 #i expanded to 2
3 #i expanded to 3
$ argtester () { for (( i=1; i<="$#"; i++ )); do echo "${!i}";done; }; argtester -ab -cd -ef
-ab # i=1 --> expanded to $1 ---> expanded to first argument sent to function
-cd # i=2 --> expanded to $2 ---> expanded to second argument sent to function
-ef # i=3 --> expanded to $3 ---> expanded to third argument sent to function
Vervanging van standaardwaarde
${parameter:-word}
Als de parameter is uitgeschakeld of nul is, wordt de uitbreiding van het woord vervangen. Anders wordt de waarde van parameter vervangen.
$ unset var
$ echo "${var:-XX}" # Parameter is unset -> expansion XX occurs
XX
$ var="" # Parameter is null -> expansion XX occurs
$ echo "${var:-XX}"
XX
$ var=23 # Parameter is not null -> original expansion occurs
$ echo "${var:-XX}"
23
${parameter:=word}
Als de parameter is uitgeschakeld of nul is, wordt de uitbreiding van het woord toegewezen aan de parameter. De waarde van parameter wordt dan vervangen. Positieparameters en speciale parameters kunnen op deze manier niet worden toegewezen.
$ unset var
$ echo "${var:=XX}" # Parameter is unset -> word is assigned to XX
XX
$ echo "$var"
XX
$ var="" # Parameter is null -> word is assigned to XX
$ echo "${var:=XX}"
XX
$ echo "$var"
XX
$ var=23 # Parameter is not null -> no assignment occurs
$ echo "${var:=XX}"
23
$ echo "$var"
23
Fout als variabele leeg of uitgeschakeld is
De semantiek hiervoor is vergelijkbaar met die van standaardwaardevervanging, maar in plaats van een standaardwaarde te vervangen, loopt het fout met het opgegeven foutbericht. De formulieren zijn ${VARNAME?ERRMSG}
en ${VARNAME:?ERRMSG}
. Het formulier met :
geeft een fout in onze als de variabele is uitgeschakeld of leeg is , terwijl het formulier zonder alleen een fout maakt als de variabele is uitgeschakeld . Als een fout wordt gegenereerd, wordt de ERRMSG
uitgevoerd en wordt de ERRMSG
ingesteld op 1
.
#!/bin/bash
FOO=
# ./script.sh: line 4: FOO: EMPTY
echo "FOO is ${FOO:?EMPTY}"
# FOO is
echo "FOO is ${FOO?UNSET}"
# ./script.sh: line 8: BAR: EMPTY
echo "BAR is ${BAR:?EMPTY}"
# ./script.sh: line 10: BAR: UNSET
echo "BAR is ${BAR?UNSET}"
Het volledige voorbeeld uitvoeren boven elk van de foutieve echo-instructies moet worden uitgeschakeld om door te gaan.
Verwijder een patroon aan het begin van een string
Kortste wedstrijd:
$ a='I am a string'
$ echo "${a#*a}"
m a string
Langste wedstrijd:
$ echo "${a##*a}"
string
Verwijder een patroon aan het einde van een string
Kortste wedstrijd:
$ a='I am a string'
$ echo "${a%a*}"
I am
Langste wedstrijd:
$ echo "${a%%a*}"
I
Vervang patroon in string
Eerste wedstrijd:
$ a='I am a string'
$ echo "${a/a/A}"
I Am a string
Alle wedstrijden:
$ echo "${a//a/A}"
I Am A string
Match aan het begin:
$ echo "${a/#I/y}"
y am a string
Match aan het einde:
$ echo "${a/%g/N}"
I am a strinN
Vervang een patroon door niets:
$ echo "${a/g/}"
I am a strin
Voorvoegsel toevoegen aan arrayitems:
$ A=(hello world)
$ echo "${A[@]/#/R}"
Rhello Rworld
Munging tijdens uitbreiding
Variabelen hoeven niet noodzakelijkerwijs uit te breiden naar hun waarden - substrings kunnen tijdens de uitbreiding worden geëxtraheerd, wat handig kan zijn voor het extraheren van bestandsextensies of delen van paden. Globbing karakters behouden hun gebruikelijke betekenissen, dus .*
Verwijst naar een letterlijke punt, gevolgd door een willekeurige reeks karakters; het is geen reguliere uitdrukking.
$ v=foo-bar-baz
$ echo ${v%%-*}
foo
$ echo ${v%-*}
foo-bar
$ echo ${v##*-}
baz
$ echo ${v#*-}
bar-baz
Het is ook mogelijk om een variabele uit te breiden met een standaardwaarde - zeg dat ik de editor van de gebruiker wil oproepen, maar als ze er geen hebben ingesteld, zou ik ze vim
willen geven.
$ EDITOR=nano
$ ${EDITOR:-vim} /tmp/some_file
# opens nano
$ unset EDITOR
$ $ ${EDITOR:-vim} /tmp/some_file
# opens vim
Er zijn twee verschillende manieren om deze uitbreiding uit te voeren, die verschillen in of de relevante variabele leeg of niet-ingesteld is. Gebruik :-
gebruikt de standaardwaarde als de variabele is uitgeschakeld of leeg is, terwijl -
gebruikt alleen de standaardwaarde als de variabele is uitgeschakeld, maar gebruikt de variabele als deze is ingesteld op de lege tekenreeks:
$ a="set"
$ b=""
$ unset c
$ echo ${a:-default_a} ${b:-default_b} ${c:-default_c}
set default_b default_c
$ echo ${a-default_a} ${b-default_b} ${c-default_c}
set default_c
Net als bij standaardwaarden kunnen alternatieven worden gegeven; waar een standaard wordt gebruikt als een bepaalde variabele niet beschikbaar is, wordt een alternatief gebruikt als de variabele beschikbaar is.
$ a="set"
$ b=""
$ echo ${a:+alternative_a} ${b:+alternative_b}
alternative_a
Opmerkend dat deze uitbreidingen kunnen worden genest, wordt het gebruik van alternatieven bijzonder nuttig bij het leveren van argumenten voor command line vlaggen;
$ output_file=/tmp/foo
$ wget ${output_file:+"-o ${output_file}"} www.stackexchange.com
# expands to wget -o /tmp/foo www.stackexchange.com
$ unset output_file
$ wget ${output_file:+"-o ${output_file}"} www.stackexchange.com
# expands to wget www.stackexchange.com
Parameteruitbreiding en bestandsnamen
U kunt Bash Parameter Expansion gebruiken om gemeenschappelijke bestandsnaam-processing operaties zoals emuleren basename
en dirname
.
We zullen dit gebruiken als ons voorbeeldpad:
FILENAME="/tmp/example/myfile.txt"
Om dirname
te emuleren en de dirname
van een bestandspad terug te geven:
echo "${FILENAME%/*}"
#Out: /tmp/example
Om basename $FILENAME
te emuleren en de bestandsnaam van een bestandspad terug te geven:
echo "${FILENAME##*/}"
#Out: myfile.txt
Om basename $FILENAME .txt
te emuleren en de bestandsnaam zonder .txt.
uitbreiding:
BASENAME="${FILENAME##*/}"
echo "${BASENAME%%.txt}"
#Out: myfile