Sök…


Introduktion

Tecknet $ introducerar parameterutvidgning, kommandosubstitution eller aritmetisk expansion. Parameternamnet eller symbolen som ska utvidgas kan vara inneslutet i hängslen, vilket är valfritt men tjänar till att skydda variabeln som ska utvidgas från tecken omedelbart efter den som kan tolkas som en del av namnet.

Läs mer i Bash Användarmanual .

Syntax

  • $ {parameter: offset} # Substring börjar vid offset
  • $ {parameter: offset: length} # Substring of length "length" från offset
  • $ {# parameter} # Längd på parametern
  • $ {parameter / pattern / string} # Ersätt den första förekomsten av mönster med sträng
  • $ {parameter // pattern / string} # Ersätt alla förekomster av mönster med sträng
  • $ {parameter / # pattern / string} # Ersätt mönster med sträng om mönstret är i början
  • $ {parameter /% pattern / string} # Byt ut mönster med sträng om mönstret slutar
  • $ {parameter # mönster} # Ta bort kortaste matchning av mönster från början av parametern
  • $ {parameter ## pattern} # Ta bort den längsta matchningen av mönster från början av parametern
  • $ {parameter% mönster} # Ta bort kortaste matchning av mönster från slutet av parametern
  • $ {parameter %% mönster} # Ta bort den längsta matchningen av mönster från slutet av parametern
  • $ {parameter: -word} # Expandera till ord om parameter inte är inställd / undefined
  • $ {parameter: = word} # Expandera till ord om parameter avmarkeras / undefineras och ställer in parameter
  • $ {parameter: + word} # Expandera till ord om parametern är inställd / definierad

Underlag och delstråk

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
4,2
# 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

Samma utvidgningar gäller om parametern är en positionsparameter eller elementet i en subskriven array :

# 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

Analoga utvidgningar gäller för positionsparametrar , där offset är en-baserad:

# 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

Substringsutvidgning kan användas med indexerade matriser :

# 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

Längd på parametern

# Length of a string
$ var='12345'
$ echo "${#var}"
5

Observera att det är längden i antal tecken som inte nödvändigtvis är samma som antalet byte (som i UTF-8 där de flesta tecken är kodade i mer än en byte), och inte heller antalet glyfer / grafema (av vilka några är kombinationer av tecken), och det är inte nödvändigtvis samma som visningsbredden.

# 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

Ändra fallet med alfabetiska tecken

4,0

För stora versaler

$ 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

För små bokstäver

$ 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

Växla fall

$ v="Hello World"
# All chars
$ echo "${v~~}"
hELLO wORLD
$ echo "${v~}"
# Just the first char
hello World

Parameter indirektion

Bash indirection tillåter att få värdet på en variabel vars namn finns i en annan variabel. Exempel på variabler:

$ red="the color red"
$ green="the color green"

$ color=red
$ echo "${!color}"
the color red
$ color=green
$ echo "${!color}"
the color green

Några fler exempel som visar den indirekta expansionsanvändningen:

 $ foo=10
 $ x=foo
 $ echo ${x}      #Classic variable print  
 foo  
 
 $ foo=10
 $ x=foo
 $ echo ${!x}     #Indirect expansion
 10

Ytterligare ett exempel:

$ 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

Standardvärdesersättning

${parameter:-word}

Om parametern är inställd eller noll, ersätts utvidgningen av ord. Annars ersätts parametervärdet.

$ 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}

Om parametern är inställd eller noll tilldelas utvidgningen av ord till parametern. Värdet på parametern ersätts sedan. Positioneringsparametrar och specialparametrar kanske inte tilldelas på detta sätt.

$ 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

Fel om variabeln är tom eller inte inställd

Semantiken för detta liknar den för standardvärdesersättning, men istället för att ersätta ett standardvärde, felar det ut med det medföljande felmeddelandet. Formerna är ${VARNAME?ERRMSG} och ${VARNAME:?ERRMSG} . Formuläret med : kommer att fel vår om variabeln är inställd eller tom , medan formen utan kommer bara att fel ut om variabeln är inställd . Om ett fel kastas, ERRMSG ut och utgångskoden är inställd på 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}"

Kör det fullständiga exemplet ovanför vart och ett av de felaktiga ekoutdragen måste kommenteras för att fortsätta.

Radera ett mönster från början av en sträng

Kortaste matchen:

$ a='I am a string'
$ echo "${a#*a}"
m a string

Längsta match:

$ echo "${a##*a}"
 string

Radera ett mönster från slutet av en sträng

Kortaste matchen:

$ a='I am a string'
$ echo "${a%a*}"
I am 

Längsta match:

$ echo "${a%%a*}"
I 

Byt ut mönstret i strängen

Första matchen:

$ a='I am a string'
$ echo "${a/a/A}"
I Am a string

Alla matcher:

$ echo "${a//a/A}"
I Am A string

Match i början:

$ echo "${a/#I/y}"
y am a string

Match i slutet:

$ echo "${a/%g/N}"
I am a strinN

Byt ut ett mönster med ingenting:

$ echo "${a/g/}"
I am a strin

Lägg till prefix till arrayobjekt:

$ A=(hello world)
$ echo "${A[@]/#/R}"
Rhello Rworld

Munging under expansion

Variabler behöver inte nödvändigtvis expandera till sina värden - underlag kan extraheras under expansion, vilket kan vara användbart för att extrahera filändelser eller delar av sökvägar. Glödande karaktärer behåller sin vanliga betydelse, så .* Hänvisar till en bokstavlig prick, följt av valfri teckenföljd; det är inte ett vanligt uttryck.

$ v=foo-bar-baz
$ echo ${v%%-*}
foo
$ echo ${v%-*}
foo-bar
$ echo ${v##*-}
baz
$ echo ${v#*-}
bar-baz

Det är också möjligt att utöka en variabel med ett standardvärde - säg att jag vill åberopa användarens redigerare, men om de inte har ställt in en skulle jag vilja ge dem vim .

$ EDITOR=nano
$ ${EDITOR:-vim} /tmp/some_file
# opens nano
$ unset EDITOR
$ $ ${EDITOR:-vim} /tmp/some_file
# opens vim

Det finns två olika sätt att utföra denna utvidgning, som skiljer sig i om den relevanta variabeln är tom eller inte inställd. Använda :- kommer att använda standarden om variabeln är antingen inställd eller tom, medan - bara använder standarden om variabeln är inställd, men kommer att använda variabeln om den är inställd på den tomma strängen:

$ 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

I likhet med standardvärden kan alternativ ges; där en standard används om en viss variabel inte är tillgänglig, används ett alternativ om variabeln är tillgänglig.

$ a="set"
$ b=""
$ echo ${a:+alternative_a} ${b:+alternative_b}
alternative_a

Att notera att dessa utvidgningar kan häckas, att använda alternativ blir särskilt användbart när man tillhandahåller argument till kommandoradsflaggor;

$ 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 

Parameterutvidgning och filnamn

Du kan använda Bash Parameter Expansion för att emulera vanliga basename som basename och dirname .

Vi kommer att använda detta som vår exempelväg:

FILENAME="/tmp/example/myfile.txt"

dirname emulerar du dirname och returnerar dirname :

echo "${FILENAME%/*}"
#Out: /tmp/example

basename $FILENAME emulerar du basename $FILENAME och returnerar filnamnet på en filväg:

echo "${FILENAME##*/}"
#Out: myfile.txt

För att emulera basename $FILENAME .txt och returnera filnamnet utan .txt. förlängning:

BASENAME="${FILENAME##*/}"
echo "${BASENAME%%.txt}"
#Out: myfile


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow