Bash
Bash Parameter Expansion
Ricerca…
introduzione
Il carattere $
introduce l'espansione dei parametri, la sostituzione dei comandi o l'espansione aritmetica. Il nome del parametro o il simbolo da espandere possono essere racchiusi tra parentesi, che sono opzionali ma servono a proteggere la variabile da espandere dai caratteri immediatamente successivi che potrebbero essere interpretati come parte del nome.
Maggiori informazioni nel Bash User Manual .
Sintassi
- $ {parametro: offset} # Sottostringa a partire da offset
- $ {parametro: offset: lunghezza} # Sottostringa di lunghezza "lunghezza" a partire da offset
- $ {parametro #} Lunghezza del parametro
- $ {parameter / pattern / string} # Sostituisce la prima occorrenza di pattern con una stringa
- $ {parametro // modello / stringa} # Sostituisce tutte le occorrenze del modello con una stringa
- $ {parameter / # pattern / string} # Sostituisce pattern con string se pattern è all'inizio
- $ {parametro /% modello / stringa} # Sostituisce il motivo con una stringa se il modello è alla fine
- $ {parameter # pattern} # Rimuove la corrispondenza più breve di pattern dall'inizio del parametro
- $ {parameter ## pattern} # Rimuove la corrispondenza più lunga del pattern dall'inizio del parametro
- $ {parameter% pattern} # Rimuove la corrispondenza più breve di pattern dalla fine del parametro
- $ {parameter %% pattern} # Rimuove la corrispondenza più lunga del pattern dalla fine del parametro
- $ {parametro: -word} # Espandi a word se parametro unset / undefined
- $ {parameter: = word} # Espandi a word se parametro unset / undefined e set parameter
- $ {parametro: + word} # Espandi a word se il parametro è impostato / definito
Sottostringhe e subarray
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
Le stesse espansioni si applicano se il parametro è un parametro posizionale o l' elemento di un array con indice :
# 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
Espansioni analoghe si applicano ai parametri posizionali , dove gli offset sono basati su uno:
# 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
L'espansione della sottostringa può essere utilizzata con gli array indicizzati :
# 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
Lunghezza del parametro
# Length of a string
$ var='12345'
$ echo "${#var}"
5
Si noti che è la lunghezza in numero di caratteri che non è necessariamente uguale al numero di byte (come in UTF-8 dove la maggior parte dei caratteri sono codificati in più di un byte), né il numero di glifi / grafemi (alcuni dei quali sono combinazioni di caratteri), né è necessariamente uguale alla larghezza del display.
# 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
Modifica del caso di caratteri alfabetici
In maiuscolo
$ 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
In lettere minuscole
$ 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
Attiva / disattiva caso
$ v="Hello World"
# All chars
$ echo "${v~~}"
hELLO wORLD
$ echo "${v~}"
# Just the first char
hello World
Parametro indiretto
Bash
indirection consente di ottenere il valore di una variabile il cui nome è contenuto in un'altra variabile. Esempio di variabili:
$ red="the color red"
$ green="the color green"
$ color=red
$ echo "${!color}"
the color red
$ color=green
$ echo "${!color}"
the color green
Alcuni altri esempi che dimostrano l'utilizzo dell'espansione indiretta:
$ foo=10
$ x=foo
$ echo ${x} #Classic variable print
foo
$ foo=10
$ x=foo
$ echo ${!x} #Indirect expansion
10
Un altro esempio:
$ 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
Sostituzione del valore predefinito
${parameter:-word}
Se il parametro non è impostato o è nullo, l'espansione della parola viene sostituita. Altrimenti, il valore del parametro viene sostituito.
$ 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}
Se il parametro non è impostato o è nullo, l'espansione della parola viene assegnata al parametro. Il valore del parametro viene quindi sostituito. I parametri posizionali e i parametri speciali non possono essere assegnati in questo modo.
$ 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
Errore se la variabile è vuota o non impostata
La semantica per questo è simile a quella della sostituzione del valore di default, ma invece di sostituire un valore predefinito, viene eliminato con il messaggio di errore fornito. I moduli sono ${VARNAME?ERRMSG}
e ${VARNAME:?ERRMSG}
. Il modulo con :
errore nostro se la variabile non è impostata o vuota , mentre il modulo senza verrà escluso solo se la variabile non è impostata . Se viene generato un errore, viene emesso ERRMSG
e il codice di uscita è impostato su 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}"
L'esecuzione dell'esempio completo sopra ciascuna delle istruzioni di errore dell'eco deve essere commentata per procedere.
Elimina un pattern dall'inizio di una stringa
Partita più breve:
$ a='I am a string'
$ echo "${a#*a}"
m a string
La partita più lunga:
$ echo "${a##*a}"
string
Elimina un pattern dalla fine di una stringa
Partita più breve:
$ a='I am a string'
$ echo "${a%a*}"
I am
La partita più lunga:
$ echo "${a%%a*}"
I
Sostituisci il motivo nella stringa
Prima partita:
$ a='I am a string'
$ echo "${a/a/A}"
I Am a string
Tutte le partite:
$ echo "${a//a/A}"
I Am A string
Partita all'inizio:
$ echo "${a/#I/y}"
y am a string
Partita alla fine:
$ echo "${a/%g/N}"
I am a strinN
Sostituisci un motivo con niente:
$ echo "${a/g/}"
I am a strin
Aggiungi prefisso agli elementi dell'array:
$ A=(hello world)
$ echo "${A[@]/#/R}"
Rhello Rworld
Munging durante l'espansione
Le variabili non devono necessariamente espandersi ai loro valori - le sottostringhe possono essere estratte durante l'espansione, che può essere utile per estrarre estensioni di file o parti di percorsi. I personaggi oscuri mantengono i loro soliti significati, così .*
riferisce a un punto letterale, seguito da qualsiasi sequenza di caratteri; non è un'espressione regolare.
$ v=foo-bar-baz
$ echo ${v%%-*}
foo
$ echo ${v%-*}
foo-bar
$ echo ${v##*-}
baz
$ echo ${v#*-}
bar-baz
È anche possibile espandere una variabile usando un valore predefinito - diciamo che voglio richiamare l'editor dell'utente, ma se non ne hanno impostato uno mi piacerebbe dargli un vim
.
$ EDITOR=nano
$ ${EDITOR:-vim} /tmp/some_file
# opens nano
$ unset EDITOR
$ $ ${EDITOR:-vim} /tmp/some_file
# opens vim
Esistono due modi diversi per eseguire questa espansione, che differiscono se la variabile rilevante è vuota o non impostata. Usando :-
userà il valore predefinito se la variabile è non impostata o vuota, mentre -
usa il valore predefinito solo se la variabile non è impostata, ma utilizzerà la variabile se è impostata sulla stringa vuota:
$ 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
Analogamente alle impostazioni predefinite, è possibile fornire alternative; dove viene utilizzato un valore predefinito se una determinata variabile non è disponibile, viene utilizzata un'alternativa se la variabile è disponibile.
$ a="set"
$ b=""
$ echo ${a:+alternative_a} ${b:+alternative_b}
alternative_a
Notando che queste espansioni possono essere annidate, l'uso di alternative diventa particolarmente utile quando si forniscono argomenti ai flag della riga di comando;
$ 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
Espansione dei parametri e nomi di file
È possibile utilizzare Bash Parameter Expansion per emulare operazioni di elaborazione dei nomi di file comuni come basename
e dirname
.
Utilizzeremo questo come nostro esempio di percorso:
FILENAME="/tmp/example/myfile.txt"
Per emulare dirname
e restituire il nome della directory di un percorso file:
echo "${FILENAME%/*}"
#Out: /tmp/example
Per emulare basename $FILENAME
e restituire il nome file di un percorso file:
echo "${FILENAME##*/}"
#Out: myfile.txt
Per emulare basename $FILENAME .txt
e restituire il nome file senza .txt.
estensione:
BASENAME="${FILENAME##*/}"
echo "${BASENAME%%.txt}"
#Out: myfile