Bash komut dosyası hatası [:! =: Tekli operatör bekleniyor


99

Komut dosyamda, ilk ve tek argümanın -v'ye eşit olup olmadığını kontrol etmeye çalışıyorum, ancak bu isteğe bağlı bir argüman. Bir if ifadesi kullanıyorum ancak tekli operatörün beklenen hatasını almaya devam ediyorum.

kod bu:

if [ $1 != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

Düzenle:

Daha spesifik olmalıyım: Yukarıdaki komut dosyasının bu kısmı isteğe bağlı bir argümanı kontrol ediyor ve ardından argüman girilmezse, programın geri kalanını çalıştırmalıdır.

#!/bin/bash

if [ "$#" -gt "1" ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" = -v ]; then
   echo "`ps -ef | grep -v '\['`"
else
   echo "`ps -ef | grep '\[' | grep root`"
fi

... bu arada, istediğini düşünüyorum echo "usage: $0 [-v]"; $-geçerli komut dosyasının adını değil, etkin kabuk seçeneği bayraklarını gösterir.
Charles Duffy

Bu kısmı doğru yaptım, mevcut betiğin adını göstermesini istiyorum.
user3380240

4
Stackoverflow'a ve özellikle de bash etiketine hoş geldiniz! Check out etiketi wiki gibi yararlı araçlar ve kaynaklar için shellcheck (her zaman açıklamaz rağmen) böyle birçok sorunu işaret edecektir.
o diğer adam

user3380240 @, $-olduğu değil şimdiki komut adı. $0dır-dir.
Charles Duffy

Üzgünüm, bu bir yazım hatasıydı.
user3380240

Yanıtlar:


196

Alıntılar!

if [ "$1" != -v ]; then

Aksi takdirde, $1tamamen boşaldığında testiniz şöyle olur:

[ != -v ]

onun yerine

[ "" != -v ]

... ve !=tekli bir operatör değildir (yani, yalnızca tek bir argüman alabilen).


9
Veya taşınabilirlik konusunda endişeleriniz yoksa, çift parantezler kullanabilirsiniz, bunların içinde değişken genişletmelerin alıntılanmasına gerek yoktur: if [[ $1 != -v ]]; then
Mike Holt

@MikeHolt, gerçekten - Bunu yukarıdaki soruya yapılan bir yorumda gündeme getirdim.
Charles Duffy

@DanielDinnyes, eğer IFS=1, o [ $# -eq 1 ]zaman çok iyi davranmaz, oysa [ "$#" -eq 1 ]o zaman bile amaçlandığı gibi davranır. Bu patolojik bir durum elbette, ama seçim verildiğinde bunlara sahip olmayan bir yazılım yazmak daha iyidir.
Charles Duffy

-2

Ya da aşırı aşırılık gibi görünen ama aslında basit olan şey için ... Hemen hemen tüm davalarınızı kapsar ve boş dizeler veya tekli endişeler yoktur.

İlk argümanın '-v' olması durumunda, koşulunuzu yapın ps -ef, aksi takdirde diğer tüm durumlarda kullanımı atın.

#!/bin/sh
case $1 in
  '-v') if [ "$1" = -v ]; then
         echo "`ps -ef | grep -v '\['`"
        else
         echo "`ps -ef | grep '\[' | grep root`"
        fi;;
     *) echo "usage: $0 [-v]"
        exit 1;; #It is good practice to throw a code, hence allowing $? check
esac

Kişi '-v' argümanının nerede olduğu umurunda değilse, durumu bir döngünün içine bırakın. Tüm bağımsız değişkenleri yürümeye ve herhangi bir yerde '-v' bulmaya izin verir (eğer varsa). Bu, komut satırı bağımsız değişken sırasının önemli olmadığı anlamına gelir. Önceden uyarılalım, sunulduğu gibi, arg_match değişkeni ayarlanmıştır, bu nedenle sadece bir işarettir. Birden çok '-v' argümanına izin verir. Diğer tüm '-v' oluşumlarını yeterince kolay görmezden gelebiliriz.

#!/bin/sh

usage ()
 {
  echo "usage: $0 [-v]"
  exit 1
 }

unset arg_match

for arg in $*
 do
  case $arg in
    '-v') if [ "$arg" = -v ]; then
           echo "`ps -ef | grep -v '\['`"
          else
           echo "`ps -ef | grep '\[' | grep root`"
          fi
          arg_match=1;; # this is set, but could increment.
       *) ;;
  esac
done

if [ ! $arg_match ]
 then
  usage
fi

Ancak, aşağıdaki gibi durumlarda kullanmak için uygun olan bir argümanın birden fazla oluşumuna izin verin:

$ adduser -u:sam -s -f -u:bob -trace -verbose

Argümanların sırasını önemsemiyoruz ve hatta çoklu -u argümanlarına izin veriyoruz. Evet, aşağıdakilere de izin vermek basit bir konudur:

$ adduser -u sam -s -f -u bob -trace -verbose

$*bu bağlamda kullanılmamalıdır: Öğeleri hem dizgiye bölünmüş hem de küresel genişletilmiş bir dizede birleştirir; aksine "$@", öğeleri kesin orijinal değerleriyle bırakır. Ve shellcheck.net'in yakalayacağı bazı alıntıları kaçırıyorsunuz (bu alıntıların neden önemli olduğunu açıklayan bir wiki sayfasına bağlı uyarılar).
Charles Duffy

Somut bir örnek olarak düşünün -U'Bob Barker'; for arg in $*olarak -UBobve sonra Barkerayrı bir öğe olarak görecek ; oysa for item in "$@"göreceksiniz -UBob Barkertek bir dize.
Charles Duffy
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.