Bash
Wyrażenia warunkowe
Szukaj…
Składnia
- [[-OP $ nazwa pliku]]
- [[$ plik1 -OP $ plik2]]
- [[-z $ string]]
- [[-n $ ciąg]]
- [["$ string1" == "$ string2"]]
- [["$ string1" == $ wzorzec]]
Uwagi
Składnia [[ … ]]
otacza wbudowane wyrażenia warunkowe bash. Zauważ, że wymagane są spacje po obu stronach nawiasów.
Wyrażenia warunkowe mogą używać jednoargumentowych i binarnych operatorów do testowania właściwości ciągów, liczb całkowitych i plików. Mogą również korzystać z operatorów logicznych &&
, ||
i !
.
Porównanie plików
if [[ $file1 -ef $file2 ]]; then
echo "$file1 and $file2 are the same file"
fi
„Ten sam plik” oznacza, że modyfikacja jednego z plików na miejscu wpływa na drugi. Dwa pliki mogą być takie same, nawet jeśli mają różne nazwy, na przykład jeśli są dowiązaniami stałymi lub jeśli są dowiązaniami symbolicznymi z tym samym celem lub jeśli jeden jest dowiązaniem symbolicznym skierowanym do drugiego.
Jeśli dwa pliki mają tę samą zawartość, ale są odrębnymi plikami (tak, że modyfikowanie jednego nie wpływa na drugi), to -ef
zgłasza je jako różne. Jeśli chcesz porównać dwa pliki bajt po bajcie, użyj narzędzia cmp
.
if cmp -s -- "$file1" "$file2"; then
echo "$file1 and $file2 have identical contents"
else
echo "$file1 and $file2 differ"
fi
Aby utworzyć czytelną dla człowieka listę różnic między plikami tekstowymi, użyj narzędzia diff
.
if diff -u "$file1" "$file2"; then
echo "$file1 and $file2 have identical contents"
else
: # the differences between the files have been listed
fi
Testy dostępu do plików
if [[ -r $filename ]]; then
echo "$filename is a readable file"
fi
if [[ -w $filename ]]; then
echo "$filename is a writable file"
fi
if [[ -x $filename ]]; then
echo "$filename is an executable file"
fi
Testy te uwzględniają uprawnienia i własność w celu ustalenia, czy skrypt (lub programy uruchomione ze skryptu) może uzyskać dostęp do pliku.
Uwaga na warunki wyścigu (TOCTOU) : fakt, że test się teraz powiedzie, nie oznacza, że nadal obowiązuje on w następnym wierszu. Zwykle lepiej jest spróbować uzyskać dostęp do pliku i poradzić sobie z błędem, niż najpierw przetestować, a następnie i tak poradzić sobie z błędem, jeśli plik w międzyczasie się zmienił.
Porównania numeryczne
W porównaniach numerycznych używamy operatorów -eq
i przyjaciół
if [[ $num1 -eq $num2 ]]; then
echo "$num1 == $num2"
fi
if [[ $num1 -le $num2 ]]; then
echo "$num1 <= $num2"
fi
Istnieje sześć operatorów numerycznych:
-
-eq
równe -
-ne
jest równy -
-le
mniejszy lub równy -
-lt
mniej niż -
-ge
większy lub równy -
-gt
większy niż
Zauważ, że operatory <
i >
wewnątrz [[ … ]]
porównują ciągi, a nie liczby.
if [[ 9 -lt 10 ]]; then
echo "9 is before 10 in numeric order"
fi
if [[ 9 > 10 ]]; then
echo "9 is after 10 in lexicographic order"
fi
Dwie strony muszą być liczbami zapisanymi dziesiętnie (lub ósemkowo z wiodącym zerem). Alternatywnie można użyć składni wyrażeń arytmetycznych ((…))
, która wykonuje obliczenia liczb całkowitych w składni podobnej do C / Java /…
x=2
if ((2*x == 4)); then
echo "2 times 2 is 4"
fi
((x += 1))
echo "2 plus 1 is $x"
Porównanie i dopasowanie ciągów
Porównanie ciągów używa operatora ==
pomiędzy ciągami cytowanymi . Operator !=
Neguje porównanie.
if [[ "$string1" == "$string2" ]]; then
echo "\$string1 and \$string2 are identical"
fi
if [[ "$string1" != "$string2" ]]; then
echo "\$string1 and \$string2 are not identical"
fi
Jeśli prawa strona nie jest cytowana, to jest to wzór wieloznaczny, z którym dopasowany jest $string1
.
string='abc'
pattern1='a*'
pattern2='x*'
if [[ "$string" == $pattern1 ]]; then
# the test is true
echo "The string $string matches the pattern $pattern"
fi
if [[ "$string" != $pattern2 ]]; then
# the test is false
echo "The string $string does not match the pattern $pattern"
fi
Operatory <
i >
porównują ciągi w porządku leksykograficznym (dla ciągów nie ma mniejszych lub równych lub większych lub równych operatorów).
Istnieją pojedyncze testy dla pustego łańcucha.
if [[ -n "$string" ]]; then
echo "$string is non-empty"
fi
if [[ -z "${string// }" ]]; then
echo "$string is empty or contains only spaces"
fi
if [[ -z "$string" ]]; then
echo "$string is empty"
fi
Powyżej, -z
może oznaczać, że $string
jest nieustawiony lub jest ustawiony na pusty ciąg. Aby rozróżnić puste i nieuzbrojone, użyj:
if [[ -n "${string+x}" ]]; then
echo "$string is set, possibly to the empty string"
fi
if [[ -n "${string-x}" ]]; then
echo "$string is either unset or set to a non-empty string"
fi
if [[ -z "${string+x}" ]]; then
echo "$string is unset"
fi
if [[ -z "${string-x}" ]]; then
echo "$string is set to an empty string"
fi
gdzie x
jest dowolne. Lub w formie tabeli :
+-------+-------+-----------+
$string is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [[ -z ${string} ]] | true | true | false |
| [[ -z ${string+x} ]] | true | false | false |
| [[ -z ${string-x} ]] | false | true | false |
| [[ -n ${string} ]] | false | false | true |
| [[ -n ${string+x} ]] | false | true | true |
| [[ -n ${string-x} ]] | true | false | true |
+-----------------------+-------+-------+-----------+
Alternatywnie , stan można sprawdzić w instrukcji case:
case ${var+x$var} in
(x) echo empty;;
("") echo unset;;
(x*[![:blank:]]*) echo non-blank;;
(*) echo blank
esac
Gdzie [:blank:]
to specyficzne dla ustawień regionalnych poziome odstępy (tabulator, spacja itp.).
Testy typu pliku
Operator warunkowy -e
sprawdza, czy plik istnieje (w tym wszystkie typy plików: katalogi itp.).
if [[ -e $filename ]]; then
echo "$filename exists"
fi
Istnieją również testy dla określonych typów plików.
if [[ -f $filename ]]; then
echo "$filename is a regular file"
elif [[ -d $filename ]]; then
echo "$filename is a directory"
elif [[ -p $filename ]]; then
echo "$filename is a named pipe"
elif [[ -S $filename ]]; then
echo "$filename is a named socket"
elif [[ -b $filename ]]; then
echo "$filename is a block device"
elif [[ -c $filename ]]; then
echo "$filename is a character device"
fi
if [[ -L $filename ]]; then
echo "$filename is a symbolic link (to any file type)"
fi
W przypadku dowiązania symbolicznego oprócz -L
testy te dotyczą celu i zwracają wartość false dla zerwanego łącza.
if [[ -L $filename || -e $filename ]]; then
echo "$filename exists (but may be a broken symbolic link)"
fi
if [[ -L $filename && ! -e $filename ]]; then
echo "$filename is a broken symbolic link"
fi
Testuj status wyjścia polecenia
Wyjdź ze stanu 0: sukces
Status wyjścia inny niż 0: błąd
Aby przetestować status wyjścia polecenia:
if command;then
echo 'success'
else
echo 'failure'
fi
Test jednej wkładki
Możesz robić takie rzeczy:
[[ $s = 'something' ]] && echo 'matched' || echo "didn't match"
[[ $s == 'something' ]] && echo 'matched' || echo "didn't match"
[[ $s != 'something' ]] && echo "didn't match" || echo "matched"
[[ $s -eq 10 ]] && echo 'equal' || echo "not equal"
(( $s == 10 )) && echo 'equal' || echo 'not equal'
Jeden test liniowy dla statusu wyjścia:
command && echo 'exited with 0' || echo 'non 0 exit'
cmd && cmd1 && echo 'previous cmds were successful' || echo 'one of them failed'
cmd || cmd1 #If cmd fails try cmd1