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?

pengguna3521621
sumber
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
mikeserv
sumber
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.
anak ayam
sumber
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.


sumber