Birincisi dışındaki tüm bağımsız değişkenleri işlemek (bir bash betiğinde)


444

Ben ilk argüman dosya adı için ayrılmış basit bir komut dosyası var ve diğer tüm isteğe bağlı argümanlar komut dosyasının diğer bölümlerine geçirilmelidir.

Google'ı kullanarak bu wiki'yi buldum , ancak gerçek bir örnek sağladı:

echo "${@: -1}"

Çalışmak için başka bir şey alamıyorum, örneğin:

echo "${@:2}"

veya

echo "${@:2,1}"

Terminalden "Kötü oyuncu değişikliği" alıyorum.

Sorun nedir ve bir bash betiğine geçirilen ilk bağımsız değişken dışındaki tüm işlemleri nasıl işleyebilirim?


21
Kafası karışmış birini çağırmak için yanlış mesele "{@:2}"işe yaramadı, bu yüzden yukarıdaki doğru cevap eşleşiyor.
Guvante

3
Sadece Ubuntu ve diğer birçok Linux üzerinde bulunan varsayılan kabuğu kullandınız. "$ {@: -1}" kısa çizgisinde şu şekilde yorumlanır: {parametre: -word} - Varsayılan Değerleri Kullan ve parametre tanımlanmamış veya null ise sözcüğü kullanır. Yani "$ {@: -1}" kısa çizgisinde "$ @" ile tam olarak aynı sonuçlar elde edilir. Bash kullanmak için komut dosyasında şu ilk satırı kullanın: #! / Bin / bash
luart

Yanıtlar:


660

Bunu kullan:

echo "${@:2}"

Aşağıdaki sözdizimi:

echo "${*:2}"

@Gordon'un daha önce açıkladığı gibi, bunu kullanarak *tüm argümanları boşluklarla tek bir argüman olarak birlikte çalıştırırken @, aralarındaki kopmaları korurken (bazı argümanların kendileri boşluk içeriyor olsa bile) tavsiye edilmez. ). Farkı yaratmaz echo, ancak diğer birçok komut için önemlidir.


7
Mesleğimin kötü olduğunu fark ettim: #!/usr/bin/env shBu yüzden problemlerim vardı. Örneğin, o shebang kaldırıldıktan sonra yukarıdaki gibi aynı, iyi çalışıyor
theta

110
"${@:2}"Bunun yerine kullan - kullanma *, tüm bağımsız değişkenleri boşluklarla tek bir bağımsız değişken olarak birlikte çalıştırırken @, aralarındaki kopmaları korur (bazı bağımsız değişkenlerin kendileri boşluk olsa bile). Fark farkedilmez echo, ancak diğer birçok şey için önemlidir.
Gordon Davisson

2
@GordonDavisson Burada tüm mesele argümanları birlikte çalıştırmaktır. Dosya adlarını geçseydik, doğru olurdunuz. echoonları sizin için birleştirecek kadar affedicidir; diğer komutlar bu kadar hoş olmayabilir. Sadece birini ya da diğerini kullanmayın: *ve @ve ne zaman kullanacağınız arasındaki farkı öğrenin . Onları eşit olarak kullanıyor olmalısınız. Bunun ne zaman sorun olacağına iyi bir örnek: $3Bir satır sonu ( \n) içeriyorsa , varsayılan bir $IFSdeğişkeniniz olması kaydıyla bunun yerine boşluk bırakılır.
Zenexer

1
@Zenexer: Anladığım kadarıyla, soru tüm geçmesine nasıl oldu ama ilk argüman ile, "senaryonun diğer kısmına" echosadece bir örnek olarak kullanılır - onlar bu durumda ise değil birlikte çalıştırılabilir. Deneyimlerime göre, birlikte çalışmasını istediğiniz durumlar nadirdir ( bir örnek için bu soruya bakın ) ve "$@"neredeyse her zaman istediğiniz şeydir. Ayrıca, satır sonu ile bahsettiğiniz sorun yalnızca $@(veya $*) çift tırnak işareti içinde değilse oluşur .
Gordon Davisson

@ GordonDavisson Hmm ... haklısın, şimdi bunu düşünüyorum; satır sonu sorun olmamalı. Başka bir şey düşünüyor olmalıydım. Ancak yine de onları birlikte çalıştırma konusunda katılmıyorum; $*Betiklerimde oldukça sık kullanmam gerekiyor .
Zenexer

180

/bin/shDenemek için de çalışan bir çözüm istiyorsanız

first_arg="$1"
shift
echo First argument: "$first_arg"
echo Remaining arguments: "$@"

shift [n]konum parametrelerini n kez kaydırır . Bir shiftset değeri $1değerine $2, değeri $2değerine $3değerinin azaltılması böylece, ve, $#bir kişi tarafından.


25
+1: Değişmeden önce büyük olasılıkla 1 $ 'ı bir değişkene kaydetmelisiniz.
glenn jackman

3
Şaşırtıcı bir şekilde foo=shiftbeklediğim şeyi yapmaz.
Keith Smiley

Bu eski olduğunu biliyorum, ama deneyinfoo=$(shift)
raumaan kidwai

12
@raumaankidwai Bu 2 nedenden dolayı çalışmaz: 1) shift(kabukta) çıktısı yoktur. Sadece $1her şeyi atar ve kaydırır. 2) $(...)kendi yerel argümanlarına sahip bir alt kabuk başlatır. Ebeveyni etkilemeyen alt kabuktaki argümanları kaydırır
Ben Jackson

Teşekkürler :) somecommand "$1" "${@:2}"Bu yöntemle (örneğin, "satır içi") ne yapmanın bir yolu var ?
İsimsiz


0

Başka bir şey arıyor bu karşı karşıya geldi. Gönderi oldukça eski görünse de, bash'daki en kolay çözüm, aşağıda set -- "${@:#}"# korumak istediğimiz dizi öğesinin başlangıç ​​numarası olan # kullanılarak en az (bash 4) gösterilmiştir :

    #!/bin/bash

    someVar="${1}"
    someOtherVar="${2}"
    set -- "${@:3}"
    input=${@}

    [[ "${input[*],,}" == *"someword"* ]] && someNewVar="trigger"

    echo -e "${someVar}\n${someOtherVar}\n${someNewVar}\n\n${@}"

Temel olarak, set -- "${@:3}"sadece perl kayması gibi dizideki ilk iki öğeyi çıkarır ve üçüncü de dahil olmak üzere kalan tüm öğeleri korur. Son unsurları da patlatmanın bir yolu olduğundan şüpheleniyorum.

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.