Yolları sağlam bir şekilde oluşturma


16

Bir kabuk betiğinde (örneğin zsh) birkaç değişkenim olduğunu varsayalım:

FOLDER_1, FOLDER_2, etc.

Bu değişkenler, aşağı inen klasörleri ifade eder /. Örneğin, bir yolum varsa/home/me/stuff/items

değişkenler:

FOLDER_1='home'
FOLDER_2='me'
FOLDER_3='stuff'

Şimdi, değişkenleri birleştirerek karşılık gelen yolu yeniden oluşturmak istediğimi söyleyin. Olası bir yol, yolu aşağıdaki gibi oluşturmaktır:

PATH=$FOLDER_1/$FOLDER_2/$FOLDER_3/

Bununla birlikte, bazı değişkenlerin FOLDER_iileri eğik çizgilerle geldiğini, diğerleri ise (ve hangisini bilmediğimizi) varsayalım.

FOLDER_1='home'
FOLDER_2='stuff/'
FOLDER_3='items'

Sorum şu: Yolu nasıl sağlam bir şekilde oluşturabilirim? (örneğin çift eğik çizgileri kullanmaktan kaçınmak ve olması gereken yere eklemek).

Bunu yapmak için bir yolu /her zaman değişken çiftleri arasında eklemek ve daha sonra herhangi bir çoğaltmaları silmek olduğunu seddüşündüm, ama işe yarayamıyorum ( /doğru ele aldığım emin değilim sed).

Ayrıca, tekerleği yeniden mi keşfediyorum ? (yani bunu zaten yapan herhangi bir yerleşik var mı?).

Değişkenler bir in ise Finallly, dizinin , örneğin FOLDERS, döngü olmadan bunu yapmak mümkün olurdu? (veya alternatif olarak, döngüde ancak FOLDERSdizide kaç tane olduğunu bilmeden ).

Yanıtlar:


12

printfBir dizi ile kullanabilirsiniz :

parts=("$FOLDER_1" "$FOLDER_2" "$FOLDER_3");
printf '/%s' "${parts[@]%/}"
# Use "printf -v path" to save it into a variable called "path" instead of printing it

%Operatör bu durumda, dizeleri sondaki kırpar /. Bunu uygulayarak parts[@], her dizi üyesini ayrı ayrı keser.

Bu printfhileyi anlamanın anahtarı şudur man 1 printf: "Biçim dizesi, argümanları karşılamak için gerektiği sıklıkta yeniden kullanılır."


Tek %yöntem questonda belirtilen tek eğik çizgi için çalışır. Birden fazla eğik çizgi olduğunda ${parts[@]%%/*}işe yarar . Eğik çizgi sorunu hakkında biraz daha bilgi için bir bağlantı: UNIX yolunda çift eğik çizgi ne anlama geliyor? 'Cd dir / subdir // geçerli mi ...
Peter.O

2
@fered: /*Bu durumda does içinde değil ortalama sıfır veya daha fazla eğik çizgi doğrusu, ama eğik çizgi karakterlerden herhangi sayısına göre izledi. Bu, yolunuz bir eğik çizgi ile başlarsa, sonucun boş dize olacağı anlamına gelir!
l0b0

Örneğe göre, sadece sondaki eğik çizgiler olacağını düşünmüştüm. Ancak, önde gelen eğik çizgi (ler) olasılığına uyum sağlamak için, bash extglob(regex ile) kullanılabilir .. shopt -s extglob; ${parts[@]%%/+(/)}...
Peter.O

15

Basit cevap endişelenmeyi bırakmak ve birden fazla eğik çizgiyi sevmektir. Birden çok eğik çizgi, tek bir eğik çizgi ile aynı etkiye sahiptir (ancak, başlayan bir yolun //birkaç sistemde farklı bir anlamı olması; Windows üzerindeki unix öykünme katmanları, adlandırabildiğim tek şeydir ). Bu, tasarım gereğidir ve birden çok eğik çizgi için endişelenmeden dosya adlarını bir araya getirebilmek, bu tasarım kararının önemli bir parçasıydı.

Dizi öğelerini birleştirmek için zsh'de j parametre genişletme bayrağını kullanabilirsiniz .

dir=${(j:/:)FOLDERS}

Yinelenen eğik çizgileri işteyken ezebilirsiniz, ancak bu tamamen kozmetiktir.

setopt extended_glob
dir=${${(j:/:)FOLDERS}//\/\/##/\/}

Ksh ve bash öğelerinde, $IFSayırıcı olarak ilk karakterini kullanarak bir diziye katılabilirsiniz . Daha sonra yinelenen eğik çizgileri ezebilirsiniz. shopt -s extglobBash'da, aşağıdaki snippet'in son satırındaki ksh glob'larını etkinleştirmek için yapmanız gerekir .

IFS=/
dir="${FOLDERS[*]}"
unset IFS
dir=${dir//\/+(\/)//}

3

sedSizin için nasıl çalışmıyor? sed 's|/\+|/|g'Birleştirdikten sonra veya sed 's|/||g'önce deneyin .


1

bash 4parametre ikamesinde düzenli ifade eşleşmesini sağlayan genişletilmiş globbing tanıtıldı ${var....}... Varsayılan olarak kapalıdır. Komut dosyanız için etkinleştirmek için, kabuk seçeneğini extglob ayarlamanız yeterlidir ...

$ Dir == olduğunu varsayarsak/home/me/////////stuff//items

shopt -s extglob; dir="${dir//+(\/)//}"

$ Dir sonuç değeri

/home/me/stuff/items  

İşte do-s ve-don't-s ile bazı örnekler - Bash Extended Globbing

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.