Jak porównać liczby w bash?

Mam ten skrypt, ale nie działa. Jest tak, ponieważ wydaje mi się, że nie jest w stanie ocenić porównania liczb w instrukcji if.

#!/bin/bash { read __ WIDTH; read __ HEIGHT; read __ __ BORDER_WIDTH; } < <(xwininfo -id "$(xdotool getactivewindow)" | grep -o -e "Height:.*" -e "Width:.*" -e "Border width:.*") echo "Height: $HEIGHT, Width: $WIDTH, Border width: $BORDER_WIDTH" x = 1920 if($WIDTH == x) then wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz else xdotool key Ctrl+F12 fi 

Jak mogę to naprawić?

Komentarze

  • Używaj odpowiednich porównań liczbowych – -eq dla równości itp.
  • Jeśli ' jesteś zadowolony z jednej lub kilku odpowiedzi, zagłosuj na nie. Jeśli ktoś rozwiązuje Twój problem, zaakceptowanie go to najlepszy sposób na powiedzenie " Dziękuję! " Zaakceptowanie odpowiedzi wskazuje również przyszłym czytelnikom, że odpowiedź faktycznie rozwiązała problem.

Odpowiedź

Jest kilka problemów ze skryptem:

  • bash testy są albo gotowe z test, [ .. ] lub [[ .. ]]; ( .. ) oznacza podpowłokę

  • Przypisania są wykonywane bez spacji, x = 1920 wywoła polecenie x z parametrami = i 1920. Zamiast tego użyj x=1920.

  • Nazwy zmiennych muszą być poprzedzone znakiem dolara, gdy ich używasz. Więc == x jest zły, a == $x jest dobry. (Z wyjątkiem obliczeń arytmetycznych lub rozszerzeń: (( ... )) lub $(( ... )), dzięki komentarzowi Kusalananda ).

  • Liczby należy porównać z -eq, = służy do porównania ciągów. W twoim przypadku powinno to również działać, ponieważ liczby prawdopodobnie będą przechowywane identycznie, ale lepiej jest użyć poprawnego koncepcyjnie operatora. == to niestandardowy odpowiednik =.

  • Powinieneś przyzwyczaić się do podwójnego cytowania zmiennych wszędzie tam, gdzie jest to możliwe, co na przykład zapobiega globowaniu.

Poprawię tylko linie zaczynające się od x = 1920, poprawiona wersja to:

x=1920 if [ "$WIDTH" -eq "$x" ] then wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz else xdotool key Ctrl+F12 fi 

Komentarze

  • O trzecim punkcie: Z wyjątkiem obliczeń arytmetycznych lub rozszerzeń: (( ... )) lub $(( ... )).

Odpowiedź

Jak zauważyły inne odpowiedzi, (...) wskazuje podpowłokę. Rozwinięcie arytmetyczne to ((...)), więc w przypadku bash należy użyć ((...)) lub [[ lub POSIXly [. Element (( może być używany w następujący sposób:

$ if ((1==1)); then echo "YES" ;fi YES 

Należy jednak pamiętać, że w przypadku [[, operator == wskazuje na dopasowanie do wzorca, tj. Nie jest to porównanie arytmetyczne.

Alternatywnie, jeśli naprawdę chcesz użyć operatora == z powłoką POSIX, możesz wykonać następujące czynności:

$ foo=1 $ bar=2 $ if [ $((foo==bar)) -eq 1 ]; then echo "YES"; else echo "NO"; fi NO $ bar=1 $ if [ $((foo==bar)) -eq 1 ]; then echo "YES"; else echo "NO"; fi YES 

W przypadku powłoki POSIX /bin/sh nie ma operatora ((, jednak istnieje $((, co jest interpretowane jako wynik wyrażenia arytmetycznego. Operatory porównania w nim działają w sposób podobny do C, gdzie 1 oznacza prawdziwy wynik, a 0 wskazuje fałszywy wynik (w przeciwieństwie do zwykłej powłoki , gdzie 0 to sukces, a wartość niezerowa to porażka).

Odpowiedź

if(a == b) nie jest właściwą składnią do porównania liczb całkowitych Dodatkowo wywołujesz x bez wskazywania, że jest to zmienna, więc próbujesz (próbujesz) porównać wartość z ciągiem literału x. Spróbuj zamiast tego:

if [[ $WIDTH -eq $x ]] 

Komentarze

  • Cytuj swoją zmienną. Przypisanie do x jest równie błędne.
  • Kiedy cytuję zmienne w konstrukcjach [[ [...] ]], powiedziano mi, że nie ' nie trzeba. Kiedy nie ' t, powiedziano mi, że powinienem. Nie mogę wygrać.
  • -1 | Ponieważ użyłeś [[ .. ]], gdy nie jest to konieczne. W takim przypadku należy użyć zwykłego polecenia testowego.
  • @Vlastimil w jakim celu? To jest skrypt bash. ' nie ma żadnego powodu, aby w ogóle używać [.
  • Jeśli ' ponownie używając bash, dosłownie nie ma powodu, aby kiedykolwiek używać konstrukcji [ [...] ], która jest jednocześnie podzbiorem i bardziej podatną na awaria z powodu problemów z PICNIC.

Odpowiedź

Spróbuj:

# use xrandr+sed to get current screen width screenWidth=`xrandr|sed -En "/connected [0-9]+x[0-9]+/{s/^.*connected ([0-9]+)x[0-9]+.*$/\1/;p}"` # use xdotool getwindowgeometry --shell to get size/pos of window eval `xdotool getactivewindow getwindowgeometry --shell` echo $screenWidth $WIDTH # debug, to see values got from xrandr and xdotool if [[ $WIDTH = $screenWidth ]]; then wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz else xdotool key Ctrl+F12 fi 

Wyjaśnienie:

  1. W bash nie umieszczaj spacji wokół =, gdy przypisywanie wartości; przykład x=123, a nie x = 123.
  2. Aby porównać rzeczy w bash użyj [[ .. ]].
  3. xdotool ma już getwindowgeometry --shell dla bash programowanie.

Komentarze

  • -1 | Ponieważ użyłeś eval i ` niepotrzebnie

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *