Değişken genişlemesini tırnak içinde nasıl sarabilirim?


5

Bash betiğim şuna benziyor:

#!/bin/bash
set -x 

./test FLAGS=${@:2}

Ve çalıştırdığımda çalıştırılan ./script 1 2 3komut ./test FLAGS=2 3. İstediğim FLAGS="2 3".

Dördüncü çizgiyi ./test FLAGS="${@:2}"değiştirdiğimde hiçbir değişiklik olmaz.

Dördüncü çizgiyi ./test FLAGS=\"{@:2}\"elde ./test 'FLAGS="2' '3"'ettiğimde istediğim şey bu değil.

Değişkenlerimi tırnak içinde nasıl satabilirim?


Bu, XY problemi gibi gözüküyor (bu çözümle çözmeye çalıştığınız asıl probleminizden ziyade, çözüm konseptinizi soruyor). Değişken adını kullandığınızdan, FLAGSaslında burada yapmaya çalıştığınız şeyin betiğinizdeki ayrıştırma seçenekleri olması mümkün mü?
Joker

Hayır, betiğimin kendisine iletilen parametreleri kullanarak başka bir betiği yürütmesi gerekiyor. FLAGS'ı başka bir isimle değiştirin, keyfi olarak seçtim.
Derek,

testhem bir kabuk yerleşik, hem de standart bir yardımcı programdır (deneyin type -a test): programınız için farklı bir ad seçmelisiniz.
Glenn jackman

Yanıtlar:


8

kullanım

"${*:2}"

onun yerine

"${@:2}"

$@Ve ${x[@]}ve bunların varyantları, dizideki eleman başına bir "kelime" genişletmek alıntı yaparken. $*(ve ${x[*]}) ilk karakteri kullanarak bütün unsurları bir araya getirerek tek bir kelimeye genişleyin$IFS .

Hiç alıntı yapılmadıysa, her iki sürüm de kelimelerin bölünmesine maruz kalır ve herhangi bir karakterin bulunduğu yerde bölünmüş birden çok kelime oluşturur IFS.


Ben ne zaman FLAGS="${*:2}"bu sonuçlanan 'FLAGS="1 2"'ben sarma tek tırnak kurtulmak nasıl?
Derek,

1
@derek, set -xşeyleri böyle çıktı. Gerçek ./testprogram tek bir argüman alacak ancak bu tek tırnak işareti ile uğraşmak zorunda kalmayacak.
Glenn jackman

2

Yorumlara dayanarak, benim anladığım şey, ilk argümanı silmek (veya bir yere saklamak) ve sonra argümanların geri kalanını komut dosyanızın içinden çağırdığınız başka bir komut dosyasına veya komuta argüman olarak kullanmaktır.

Eğer öyleyse, oldukça kolay bir şekilde yapabilirsiniz FLAGSve betiğin parametrelerini betiğinizdeki komuta aktarmak için bir değişken ( veya başka bir şey) ayarlamanıza gerek yoktur . Aşağıdaki örneğe bakın:

#!/bin/bash
set -x

original_first_arg="$1"     # Use this line if you need to save the value to use later.

shift
mycommand "$@"

shiftKomutu a bashyerleşik. Kendi başına (herhangi bir sayı vermeden), sadece betiğin ilk argümanını (konumsal parametre) atar. Manpage'den:

   shift [n]
          The  positional  parameters  from n+1 ... are renamed to $1 ....
          Parameters represented by the numbers  $#  down  to  $#-n+1  are
          unset.   n  must  be a non-negative number less than or equal to
          $#.  If n is 0, no parameters are changed.  If n is  not  given,
          it  is assumed to be 1.  If n is greater than $#, the positional
          parameters are not changed.  The return status is  greater  than
          zero if n is greater than $# or less than zero; otherwise 0.

Ardından "$@"komut dosyasına verdiğiniz tam parametrelere genişler, eksi komuttan $1atıldığından beri ilk olanı shift.

Daha fazla okuma:


Lütfen yorum yapmadan oy kullanma. Ben bu cevaba çalışıyorum.
Joker

Zeyilname sadece doğru değil. Dokümantasyon burada biraz sorunludur, ama bunu deneyebilirsiniz: bash -c 'set abc def ghi ; echo "${*:2}"'.
Michael Homer,

Haklısın ve belgeler gerçekten berbat. Yanlış eki kaldırdım. Oyu değiştirir misiniz? :)
Wildcard

2

Komut dosyanızın argümanlarına bağlı olarak farklı parametre kümeleri istiyorsanız , bunun için işlevleri kullanabilirsiniz:

other_script(){ shift; command other_script "$@"; }
other_script "$@"

Genelde böyle yaparım. Bir işlev başka bir işlevi veya kendisini arayabilir veya yeni bir işlev tanımlayabilir - veya kendini yeniden tanımlayabilir. Her fonksiyon bir dizi alır.

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.