Periksa apakah ada salah satu parameter pada skrip bash yang cocok dengan string

67

Saya mencoba menulis skrip tempat saya ingin memeriksa apakah ada parameter yang diteruskan ke skrip bash yang cocok dengan string. Cara saya mengaturnya sekarang adalah

if [ "$3" != "-disCopperBld" -a "$4" != "-disCopperBld" -a "$5" != "-disCopperBld" -a "$6" != "-disCopperBld"]

tetapi mungkin ada sejumlah besar parameter, jadi saya bertanya-tanya apakah ada cara yang lebih baik untuk melakukan ini?

Terima kasih

EDIT: Saya mencoba potongan kode ini, dan memanggil skrip dengan opsi, -disableVenusBld, tetapi masih mencetak "Mulai membangun". Apakah saya melakukan sesuatu yang salah? Terima kasih sebelumnya!

while [ $# -ne 0 ]
do
    arg="$1"
    case "$arg" in
        -disableVenusBld)
            disableVenusBld=true
            ;;
        -disableCopperBld)
            disableCopperBld=true
            ;;
        -disableTest)
            disableTest=true
            ;;
        -disableUpdate)
            disableUpdate=true
            ;;
        *)
            nothing="true"
            ;;
    esac
    shift
done

if [ "$disableVenusBld" != true ]; then
    echo "Starting build"
fi
iman453
sumber
Terima kasih untuk balasan kalian, saya menghargai kamu akan meluangkan waktu untuk membantu saya. Saya mencoba sepotong kode, tetapi sepertinya saya tidak tahu apa yang salah. Ada ide? (Saya telah menempelkan kode dalam edit dari posting asli saya)
iman453
Hmm: itu bekerja untuk saya. Saya menambahkan #! /bin/sh -ke bagian atas apa yang Anda sertakan di sana, membuat skrip dapat dieksekusi, lalu ./t.shmencetak "Mulai membangun", tetapi ./t.sh -disableVenusBldtidak mencetak apa pun.
Norman Gray

Jawaban:

59

Sepertinya Anda melakukan penanganan opsi dalam skrip shell. Inilah ungkapan untuk itu:

#! /bin/sh -

# idiomatic parameter and option handling in sh
while test $# -gt 0
do
    case "$1" in
        --opt1) echo "option 1"
            ;;
        --opt2) echo "option 2"
            ;;
        --*) echo "bad option $1"
            ;;
        *) echo "argument $1"
            ;;
    esac
    shift
done

exit 0

(Ada beberapa konvensi untuk indentasi ;;, dan beberapa shell memungkinkan Anda untuk memberikan opsi sebagai (--opt1), untuk membantu pencocokan penjepit, tetapi ini adalah ide dasarnya)

Norman Gray
sumber
3
Sebuah shiftpernyataan digunakan ketika jumlah argumen untuk perintah tidak diketahui sebelumnya, misalnya ketika pengguna dapat memberikan banyak argumen yang mereka suka. Dalam kasus seperti itu, argumen diproses dalam satu whilelingkaran dengan kondisi pengujian $#. Kondisi ini berlaku selama jumlah argumen lebih besar dari nol. The $1variabel dan shiftpernyataan memproses setiap argumen. Jumlah argumen dikurangi setiap kali shiftdieksekusi dan akhirnya menjadi nol, di mana whileloop keluar. sumber
Serge Stroobandt
Berikut adalah contoh serupa dengan echo $1 | sedpemrosesan nilai argumen tambahan .
Serge Stroobandt
26

Ini berhasil untuk saya. Itu tidak persis apa yang Anda minta dan tidak lebih (tidak ada opsi pengolahan). Apakah itu baik atau buruk adalah latihan untuk poster :)

if [[ "$*" == *YOURSTRING* ]]
then
    echo "YES"
else
    echo "NO"
fi

Ini mengambil keuntungan dari penanganan khusus $* dan bash kurung uji [[]].

Homolka yang kaya
sumber
2
IMHO ini harus menjadi jawaban yang paling benar, karena pertanyaannya hanya perlu memeriksa keberadaan parameter. Saya telah mengedit, namun, berubah $*menjadi $@, karena string yang akan diuji mungkin memiliki spasi dan menambahkan tautan ke dokumentasi bash tentang hal itu.
h7r
9
Apakah Anda bermaksud menggunakan operator = ~? Kalau tidak, saya tidak melihat mengapa ini harus bekerja, dan memang tidak bekerja ketika saya mencoba skrip yang tepat.
Seppo Enarvi
3
Tidak bekerja bash -c 'echo args=$*; [[ "$@" == "bar" ]] && echo YES || echo NO' -- foo bar
Tobia 4-15
2
Ini membandingkan seluruh daftar argumen dengan your string. Saya pikir Anda perlu melakukan apa yang disarankan oleh jawaban ini . yaitu: bash -c 'echo args=$*; for i in "$@" ; do [[ $i == "bar" ]] && echo "Is set!" && break ; done' -- bar fooakan bekerja.
starfry
2
Jawaban ini salah selama empat tahun terakhir karena hasil edit h7r telah memecahkannya. Jawaban asli (yang sekarang telah saya pulihkan) berfungsi, asalkan "string Anda" tidak mengandung karakter glob, dan dengan beberapa positif palsu. Misalnya, jika perintahnya adalah create a new certificatedan "string Anda" adalah cat, ini akan melaporkan kecocokan karena certificate berisi cat .
Scott
8

Bagaimana dengan mencari (dengan wildcard) seluruh ruang parameter:

if [[ $@ == *'-disableVenusBld'* ]]
then

Sunting: Oke, oke, jadi itu bukan jawaban yang populer. Bagaimana dengan yang ini, sempurna !:

if [[ "${@#-disableVenusBld}" = "$@" ]]
then
    echo "Did not find disableVenusBld"
else
    echo "Found disableVenusBld"
fi

Edit2: Ok, ok, mungkin ini tidak sempurna ... Pikirkan itu hanya berfungsi jika -param ada di awal daftar dan juga akan cocok dengan -paramXZY atau -paramABC. Saya masih berpikir masalah asli dapat diselesaikan dengan sangat baik dengan manipulasi string bash, tapi saya belum cukup memecahkannya di sini ... -Bisakah Anda ??

Kaya
sumber
Saran kedua Anda - membandingkan subtitusi penyaringan dengan substitusi penuh - bekerja dengan cukup baik, dan memiliki keuntungan tidak mengganggu daftar argumen.
Donal Fellows
Bisakah Anda menjelaskan apa saran kedua (terutama ${@#)?
velop
1
@ mengembangkan Tentu! Jadi, Anda tahu itu $@adalah variabel khusus yang menampung semua argumen baris perintah? Yah saya baru saja menggunakan manipulasi string Bash pada variabel itu untuk menghapus substring "-disableVenusBld", dan kemudian saya membandingkannya dengan yang asli $@. Jadi jika $@sama -foo -barmaka ${@#-disableVenusBld}masih -foo -bar, jadi saya bisa melihat bahwa bendera yang saya cari tidak ada. Namun, jika $@sama -foo -disableVenusBld -barmaka ${@#-disableVenusBld}akan menjadi -foo -baryang tidak sama dengan $@, dengan demikian memberitahu saya bahwa bendera yang saya cari ada! Keren ya!
Kaya
@velop Pelajari lebih lanjut tentang manipulasi string Bash di sini: tldp.org/LDP/abs/html/string-manipulation.html
Rich
@Rich cukup rapi ^^, terima kasih untuk penjelasannya.
velop
4
disCopperBld=
for x; do
  if [ "$x" = "-disCopperBld" ]; then disCopperBld=1; break; fi
done
if [ -n "$disCopperBld" ]; then
  ...
fi

Jika Anda hanya perlu menguji parameter mulai dari $3, lakukan pencarian dalam suatu fungsi:

## Usage: search_trailing_parameters NEEDLE NUM "$@"
## Search NEEDLE amongst the parameters, skipping $1 through ${$NUM}.
search_trailing_parameters () {
  needle=$1
  shift $(($2 + 2))
  for x; do
    if [ "$x" = "$needle" ]; then return 0; fi
  done
  return 1
}
if search_trailing_parameters -disCopperBld 2 "$@"; then
  ...
fi

Tapi saya heran mengapa Anda mencoba melakukan ini sejak awal, itu bukan kebutuhan umum. Biasanya, Anda akan memproses opsi secara berurutan, seperti pada jawaban Dennis untuk pertanyaan Anda sebelumnya .

Gilles 'SANGAT berhenti menjadi jahat'
sumber