Chcę połączyć wiele warunków w instrukcji if powłoki i zanegować kombinację. Mam następujący kod roboczy dla prostej kombinacji warunków:
if [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ; then
# do stuff with the files
fi
To działa dobrze. Jeśli chcę to zanegować, mogę użyć następującego działającego kodu:
if ! ( [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ) ; then
echo "Error: You done goofed."
exit 1
fi
# do stuff with the files
Działa to również zgodnie z oczekiwaniami. Jednak przychodzi mi do głowy, że nie wiem, co właściwie robią nawiasy. I chcą , aby ich używać tylko do grupowania, ale jest to faktycznie tarło podpowłoce? (Jak mogę to stwierdzić?) Jeśli tak, czy istnieje sposób na grupowanie warunków bez odradzania podpowłoki?
bash
shell-script
Dzika karta
źródło
źródło
if ! [ -f file1 ] || ! [ -f file 2 ] || ! [ -f file3 ] ; then
ale chciałbym bardziej ogólnej odpowiedzi.if [[ ! -f file1 ]] && [[ ! -f file2 ]]; then
if [ ! 1 -eq 2 ] && [ ! 2 -eq 3 ]; then echo yep; fi
i działa. Po prostu zawsze piszę testy z podwójnymi nawiasami klamrowymi w ramach nawyku. Ponadto, aby upewnić się, że tak nie jestbash
, przeprowadziłem dalsze testyif /bin/test ! 1 -eq 2 && /bin/test ! 2 -eq 3 ; then echo yep; fi
i tak też działa.[ ! -e file/. ] && [ -r file ]
spowoduje upuszczenie katalogów. neguj to, jak chcesz. oczywiście, że-d
tak.Odpowiedzi:
Musisz użyć
{ list;}
zamiast(list)
:Oba są Poleceniami grupującymi , ale
{ list;}
wykonują polecenia w bieżącym środowisku powłoki.Zauważ, że
;
in{ list;}
jest potrzebne do rozdzielenia listy od}
odwrotnego słowa, możesz również użyć innego separatora. Wymagane{
jest również spacja (lub inny separator) po .źródło
awk
częściej niż wbash
), to potrzeba spacji po otwartym nawiasie klamrowym. Wspominasz „możesz również użyć innego ogranicznika”; jakieś przykłady?zsh
, możesz użyć białych znaków&
jest to także separator, którego można użyć{ echo 1;:&}
, można również użyć wielu znaków nowej linii.they must be separated from list by whitespace or another shell metacharacter.
W bash one:metacharacter: | & ; ( ) < > space tab
. W przypadku tego konkretnego zadania uważam, że którekolwiek z& ; ) space tab
nich zadziała. .... .... Z zsh (jako komentarz)each sublist is terminated by
&',
&!', or a newline.
Możesz w pełni wykorzystać tę
test
funkcjonalność, aby osiągnąć to, czego chcesz. Ze strony podręcznika użytkownikatest
:Twój stan może wyglądać następująco:
W celu zanegowania użyj nawiasów ucieczkowych:
źródło
Aby przenośnie zanegować złożony warunek w skorupce, musisz albo zastosować prawo De Morgana i wcisnąć negację do samego końca
[
połączeń ...... lub musisz użyć
then :; else
...if ! command
nie jest przenośny i nie jest[[
.Jeśli nie potrzebujesz całkowitej przenośności, nie pisz skryptu powłoki . W rzeczywistości istnieje większe prawdopodobieństwo, że znajdziesz
/usr/bin/perl
na losowo wybranym Uniksiebash
.źródło
!
jest POSIX, który obecnie jest wystarczająco przenośny. Nawet systemy, które nadal są dostarczane z powłoką Bourne'a, mają również POSIX sh w innym systemie plików, którego można użyć do interpretacji standardowej składni./bin/sh
. Skrypty Autoconf działają tak, jak sugerujesz, ale myślę, że wszyscy wiemy, jak mało to poparcia.inni zauważyli
{
złożone;}
grupowanie poleceń , ale jeśli wykonujesz identyczne testy na zestawie, możesz użyć innego rodzaju:... jak pokazano gdzie indziej
{ :;}
, nie ma trudności z zagnieżdżaniem poleceń złożonych ...Zauważ, że powyższe (zwykle) testy zwykłych plików. Jeśli szukasz tylko istniejących , czytelnych plików, które nie są katalogami:
Jeśli nie obchodzi Cię, czy są to katalogi, czy nie:
... działa dla każdego czytelnego , dostępnego pliku, ale prawdopodobnie zawiesi się dla programistów fifos bez / z.
źródło
To nie jest pełna odpowiedź na twoje główne pytanie, ale zauważyłem, że w komentarzu wspominasz o testach złożonych (plik czytelny); na przykład,
Możesz to trochę skonsolidować, definiując funkcję powłoki; na przykład,
Dodaj obsługę błędów (np.
[ $# = 1 ]
) Do smaku. Pierwszeif
stwierdzenie powyżej można teraz skondensowaći możesz to jeszcze bardziej skrócić, skracając nazwę funkcji. Podobnie, możesz zdefiniować
not_readable_file()
(lubnrf
w skrócie) i dołączyć negację do funkcji.źródło
readable_files() { [ $# -eq 0 ] && return 1 ; for file in "$@" ; do [ -f "$file" ] && [ -r "$file" ] || return 1 ; done ; }
(Zastrzeżenie: Testowałem ten kod i działa, ale nie był to jednowierszowy. Dodałem średniki do zamieszczania tutaj, ale nie przetestowałem ich umiejscowienia.)if readable_files file1 file2 file3
nie wiemy , czy funkcja robi AND lub OR - chociaż (a) Myślę, że to dość intuicyjne, (b) jeśli nie jesteś dystrybucją skryptu, to wystarczająco dobre, jeśli masz go zrozumieć, oraz (c) ponieważ zasugerowałem skrócenie nazwy funkcji w zapomnienie, nie jestem w stanie mówić o czytelności. … (Ciąg dalszy)for file in "$@" ; do
zfor file do
- Domyślnie jest toin "$@"
, i (nieco wbrew intuicji);
jest nie tylko niepotrzebna, ale faktycznie zniechęca.Możesz również zanegować wewnątrz testów nawiasów, aby ponownie użyć oryginalnego kodu:
źródło
||
zamiast&&
||
spowoduje wykonanie predykatu, jeśli któryś z plików nie będzie obecny, nie tylko wtedy, gdy tylko wszystkie pliki nie będą obecne. NOT (A AND B AND C) jest taki sam jak (NOT A) AND (NOT B) AND (NOT C); zobacz oryginalne pytanie.||
zamiast&&
. Zobacz mój pierwszy komentarz poniżej samego pytania.not (a and b)
jest taki sam jak(not a) or (not b)
. Zobacz en.wikipedia.org/wiki/De_Morgan%27s_lawsTak, polecenia wewnątrz
(...)
są uruchamiane w podpowłoce.Aby sprawdzić, czy jesteś w podpowłoce, możesz porównać PID bieżącej powłoki z PID interaktywnej powłoki.
Przykładowe dane wyjściowe pokazujące, że nawiasy odradzają podpowłokę, a nawiasy klamrowe nie:
źródło
()
spawnuje{}
echo $$ && ( echo $$ )
aby porównać PID i były takie same, ale tuż przed przesłaniem komentarza z informacją, że się mylisz, spróbowałem jeszcze jednej rzeczy.echo $BASHPID && ( echo $BASHPID )
daje różne PIDecho $BASHPID && { echo $BASHPID; }
podaj ten sam PID, jak sugerowałbyś. Dzięki za edukację$BASHPID
, to kolejna rzecz, której mi brakowało.