Eşit olmayan sözdizimi önemli midir?


22

Komut yazarken, iftaslarımı aşağıdaki sözdizimiyle yazarım, çünkü daha sonra gelenlerin doğru olmadığını anlamam daha kolay olur.

if [ ! "$1" = "$2" ]; then

Diğerleri aşağıdaki yolun daha iyi olduğunu söylüyor

if [ "$1" != "$2" ]; then

Mesele şu ki nedenini sorup sorduğumda hiç kimsenin cevabı yok gibi görünüyor.

Peki, iki sözdizimi arasında herhangi bir fark var mı? Biri diğerinden daha mı güvenli? Yoksa bu sadece bir tercih / alışkanlık meselesi midir?


9
İlk durumda size operatörlere ayırt öncelik bilmek gerekir !(x==y)dan (!x)==y.
jimmij

@jimmij Bir dizgiyi karşılaştırırken bunun eşittir if [ ! "$string" = "one" ]değerine çevrilmediği anlamına mı geliyorsunuz ? Ve bunun değeri eşit değilse, bunun anlamı nedir? $stringoneif [ "$string" != "one"]$stringone
Jimmy_A

5
@Jimmy_A Bunun nasıl "tercüme ettiğini" bilmeniz gerektiğini kastediyorum. Operatörleri bir araya getirmek ( !=sözdizimi) sadece daha açıktır.
jimmij

Sevgili yakın seçmenler, Stéphane'nin cevabı davranışlarda maddi bir fark olduğunu gösteriyor, doğru cevap hiçbir şekilde görüşe dayalı değil.
Kevin

Yanıtlar:


35

Kozmetik / tercih argümanlarının yanı sıra, sebeplerden biri [ ! "$a" = "$b" ], köşe durumlarda başarısız olanlardan daha fazla uygulama yapılması olabilir [ "$a" != "$b" ].

Eğer uygulamalar POSIX algoritmasını takip ederse her iki durum da güvenli olmalı , ancak bugün bile (2018'in başlarında) hala başarısız olan uygulamalar var. Örneğin, şununla a='(' b=')':

$ (a='(' b=')'; busybox test "$a" != "$b"; echo "$?")
0
$ (a='(' b=')'; busybox test ! "$a" = "$b"; echo "$?")
1

İle dasholarak bulundu 0.5.8 gibi sürümler önce 0.5.9 için, shörneğin Ubuntu 16.04 tarih:

$ a='(' b=')' dash -c '[ "$a" != "$b" ]; echo "$?"'
0
$ a='(' b=')' dash -c '[ ! "$a" = "$b" ]; echo "$?"'
1

(0.5.9'da düzeltildi, bkz. https://www.mail-archive.com/dash@vger.kernel.org/msg00911.html )

Bu uygulamalar tedavi [ ! "(" = ")" ]olarak [ ! "(" "text" ")" ]olmasıdır [ ! "text" ]POSIX görev olması için ise ( "metin" boş dizge olup testi) [ ! "x" = "y" ](test, "x" ve eşitlik "y"). Bu uygulamalar başarısız olur, çünkü bu durumda yanlış testi yaparlar.

Başka bir form daha olduğuna dikkat edin:

! [ "$a" = "$b" ]

Bu bir POSIX kabuğu gerektirir (eski Bourne kabuğu ile çalışmaz).

Not, çeşitli uygulamaları ile ilgili sorunlar vardı [ "$a" = "$b" ](ve [ "$a" != "$b" ]onunla birlikte) ve yine gibi yapın [bir yerleşiği /bin/shSolaris 10 (a Bourne kabuğu POSIX kabuk olmak /usr/xpg4/bin/sh). Bu yüzden şöyle şeyler görüyorsunuz:

[ "x$a" != "x$b" ]

Scriptlerde eski sistemlere taşınabilir olmaya çalışıyor.


Yani başka bir deyişle, her iki sözdizimi de aynı şeyi yapar, hiçbir farkı yoktur, ancak ! "$a" = "b"karşılaştırmayı belirtmek için nasıl yazdığınız konusunda daha dikkatli olmanız gerekir. Örneğinizden, ikinci komutun not zerohem yararlı hem de rahatsız edici olabilecek geri döndüğünü anlıyorum . Eğer
uyuşmazlarsa çıkıp çıkmamanız

2
@Jimmy_A, hayır, bu uygulamalarda [ ! "$a" = "$b" ]sadece başarısız $aolduğu (ve $bolduğu ), bu onlar değilken onlar aynıdır iddia (ile aynı dize değil ), ama [bu durumda yanlış testi gerçekleştirdiği.
Stéphane Chazelas

Ahhh, sanırım anladım. Birinci ve üçüncü koşulun doğru olup olmadığını kontrol etmek, ikinci ve dördüncü koşul ise yanlış olup olmadığını kontrol etmek anlamına gelir. Böylece, çıkış durum kodları farklıdır. Temel olarak şunu söylemek gerekirse, 1 ve 4 değişkenleri farklıdır ve 2 ve 3 eşit değildir.
Jimmy_A

3
@Jimmy_A, hayır. Bu noktayı tamamen kaçırdınız. Eğer bu uygulamalar POSIX izledi ve ardından tüm durum kodları 0. olurdu
Joker

Anladığımdan emin olmak için, bu aşağı kaynatır: [ ! "$a" = "$b" ]bazen kaba kabarcıklı uygulamalarda yanlış ele alınır (bence cevabın ilk cümlesini az çok düzeltiyor).
Michael Burr,

8

x != ySözdizimi çünkü iyidir ! x == yhata eğilimli - farklıdır dilden dile operatörler öncelik bilgisi gerektirir. Sözdizimi ! x == yolarak yorumlanabilir !(x == y)veya (!x) == yönceliğini bağlı olarak, !vs =.


Örneğin, c++olumsuzlama ! karşılaştırma / ilişkisel işleçten önce gelir== , bu nedenle aşağıdaki kod:

#include<iostream>

using namespace std;

int main()
{
  int x=1, y=2;
  if(     x  != y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(  !  x  == y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(  !( x  == y ) ) cout<<"true"<<endl; else cout<<"false"<<endl;
  if(   (!x) == y   ) cout<<"true"<<endl; else cout<<"false"<<endl;
}

döner

true
false
true
false

awkUnix dünyasında sıkça kullanılan bir araç gibi, örneğin pek çok dilde benzer davranışlar gözlemlenebilir .


Öte yandan, operatörleri bir araya getirmek, x != ysağlam bir örüntü olarak karışıklığa yol açmaz. Dahası, teknik olarak konuşmak !=, genellikle iki değil, sadece bir operatördür, bu nedenle ayrı bir karşılaştırma ve olumsuzlamadan çok daha hızlı bir şekilde değerlendirme yapmak gerekir. Bu nedenle, her iki sözdiziminin de bash olarak çalışmasına rağmen, x != ybazı standart mantıkları izleyen kodları okumak ve bakım yapmak daha kolay olduğu için izlemenizi tavsiye ederim .


4

Bu tür şeyler çok görüş temellidir, çünkü “cevap” bireyin beyninin kablolanmasına çok kuvvetli bir şekilde bağlıdır. Anlamsal olarak doğru olsa da,NOT ( A == B ) olarak aynı(A != B ) , biri bir kişiye, diğeri diğerine daha açık olabilir. Aynı zamanda bağlama bağımlıdır. Örneğin, bir bayrak kümem varsa, anlamlar bir başkası üzerinde bir sözdiziminde daha açık olabilir:

if NOT ( fileHandleStatus == FS_OPEN )

aksine

if ( fileHandleStatus != FS_OPEN )

Ve if ( FS_OPEN != fileHandleStatus )yanlışlıkla atama ve daha sonra eşitlik testi (C gibi) dilleri =yerine ==dilleri yerine yanlışlıkla yazma kolaylığı sonucu ...
derobert
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.