Arti [“$ {1: 0: 1}” = '-']


18

Saya memiliki skrip berikut untuk meluncurkan proses MySQL:

if [ "${1:0:1}" = '-' ]; then
    set -- mysqld_safe "$@"
fi

if [ "$1" = 'mysqld_safe' ]; then
    DATADIR="/var/lib/mysql"
...

Apa artinya 1: 0: 1 dalam konteks ini?


1
Saya benar-benar ingin tahu jawabannya, tetapi saya merasa ini adalah pertanyaan yang terlalu sempit untuk SF. Saya memberikan suara untuk memigrasikannya ke situs Unix.
— Massimo

Jawaban:


19

Ini adalah tes untuk -opsi argumen putus - putus, rupanya. Agak aneh, sungguh. Ini menggunakan bashekspansi non-standar dalam upaya untuk mengekstraksi karakter pertama dan hanya karakter pertama dari $1. Ini 0adalah indeks karakter kepala dan 1panjang string. Dalam [ testseperti itu mungkin juga:

[ " -${1#?}" = " $1" ]

Tidak ada perbandingan yang cocok test, karena ia menginterpretasikan -argumen yang putus-putus - itulah sebabnya saya menggunakan ruang terdepan di sana.

Cara terbaik untuk melakukan hal semacam ini - dan cara biasanya dilakukan - adalah:

case $1 in -*) mysqld_safe "$@"; esac

1
Menutup; angka yang mengikuti titik dua ${1:0:1}adalah panjang, bukan indeks.
— chepner

Dalam cara bashism dengan [[: [[ $1 == -* ]].
— Arthur2e5

2
Secara pribadi saya tidak berpikir itu -akan menjadi masalah untuk di testsini .. POSIX memberikan definisi makna dengan jumlah argumen. Karena tidak ada opsi seperti itu yang membutuhkan dua argumen, harus aman untuk menuliskannya secara mentah.
— Arthur2e5

@ Arthur2e5 - Anda benar - mereka seharusnya tidak menjadi masalah - dan sangat mungkin tidak bermasalah sama sekali. itu masih cara yang aneh untuk melakukannya - itu hanya tidak pas. apa yang [[ : [[harus dilakukan
— mikeserv

1
@mikeserv Yah Anda harus melihat halaman web (jika Anda membaca ini dari tempat lain) .. Komentar saya seperti 'dengan START_CODE [[END_CODE: START_CODE [[$ 1 == - *]] END_CODE'. Yang pertama [[hanya nama sintaks, dan titik dua hanyalah tanda baca.
— Arthur2e5

11

Ini akan mengambil substring dari $10 ke karakter 1. Jadi Anda akan mendapatkan karakter pertama dan hanya karakter pertama dari string.

Dari bashhalaman manual 3.2:

  ${parameter:offset}
  ${parameter:offset:length}
          Substring  Expansion.   Expands  to  up to length characters of
          parameter starting at the character specified  by  offset.   If
          length is omitted, expands to the substring of parameter start-
          ing at the character specified by offset.   length  and  offset
          are  arithmetic  expressions (see ARITHMETIC EVALUATION below).
          length must evaluate to a number greater than or equal to zero.
          If  offset  evaluates  to a number less than zero, the value is
          used as an offset from the end of the value of  parameter.   If
          parameter  is  @,  the  result  is length positional parameters
          beginning at offset.  If parameter is an array name indexed  by
          @ or *, the result is the length members of the array beginning
          with ${parameter[offset]}.  A negative offset is taken relative
          to  one  greater than the maximum index of the specified array.
          Note that a negative offset must be separated from the colon by
          at  least  one space to avoid being confused with the :- expan-
          sion.  Substring indexing is zero-based unless  the  positional
          parameters are used, in which case the indexing starts at 1.

6

Ini sedang menguji bahwa karakter pertama dari argumen pertama $1adalah tanda hubung -.

1: 0: 1 adalah nilai-nilai untuk ekspansi parameter: ${parameter:offset:length}.

Itu berarti:

  • Nama: parameter bernama 1, yaitu:$1
  • Mulai: dari karakter pertama 0(dinomori dari 0).
  • Panjang: untuk 1 karakter.

Singkatnya: karakter pertama dari parameter posisi pertama $1.
Perluasan parameter tersebut tersedia dalam ksh, bash, zsh (setidaknya).


Jika Anda ingin mengubah jalur tes:

[ "${1:0:1}" = "-" ]

Opsi bash

Solusi bash yang lebih aman lainnya mungkin:

[[ $1 =~ ^- ]]
[[ $1 == -* ]]

Lebih aman karena ini tidak memiliki masalah dengan mengutip (tidak ada pemisahan dijalankan di dalam [[)

Opsi POSIXly.

Untuk cangkang yang lebih tua dan kurang mampu, dapat diubah menjadi:

[ "$(echo $1 | cut -c 1)" = "-" ]
[ "${1%%"${1#?}"}"        = "-" ]
case $1 in  -*) set -- mysqld_safe "$@";; esac

Hanya perintah case yang lebih tahan terhadap kesalahan mengutip.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.