Bir dizgenin son karakterini silmek istiyorum, bu küçük betiği denedim:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
ama "lkj" yazıyor, yanlış ne yapıyorum?
Bir dizgenin son karakterini silmek istiyorum, bu küçük betiği denedim:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
ama "lkj" yazıyor, yanlış ne yapıyorum?
Yanıtlar:
Bir POSIX kabuğunda, sözdizimi ${t:-2}farklı bir şey ifade eder - teğer tayarlanmış ve boş olmamışsa, aksi halde değere doğru genişler 2. Tek bir karakteri parametre genişletme ile kesmek için, muhtemelen istediğiniz sözdizimi${t%?}
Ki Not ksh93, bashya zsh, ${t:(-2)}veya ${t: -2}(boşluk dikkat edin) olan bir alt dize genişleme gibi yasal ama onlar (ucundan bir pozisyonda 2 karakter başlayan alt dize döndürür beri, ne istediğini muhtemelen değil yani o kaldırır ilk karakteri iarasında dize ijk).
Daha fazla bilgi için Bash Referans Kılavuzunun Shell Parametre Genişletme bölümüne bakın:
${parameter%word}en kısa son ek desen eşleştirmesini kaldırır word- bkz. Parametre Genişletme bölümüman bash
İle bashyukarıda 4.2 ve yapabileceğiniz:
${var::-1}
Örnek:
$ a=123
$ echo "${a::-1}"
12
Daha eskiler için bash(örneğin, bash 3.2.5OS X'te), kolonların arasında ve sonrasında boşluk bırakmanız gerektiğine dikkat edin:
${var: : -1}
bashsürüm 4.2-alfa ve üzeri sürümlerde çalışır , erişebileceğim sürümün önceki sürümleri çok kötü. : - /
${var:offset:lenght}yalnızca içeriye eklendi bash 4.2. Belki OSX kendi yamasını ekler bash.
son nkarakterleri, kullanılmayan bir satırdan kaldırmak içinsedVEYAawk :
> echo lkj | rev | cut -c (n+1)- | rev
yani son karakteri silebilirsiniz one character kullanarak :
> echo lkj | rev | cut -c 2- | rev
> lk
dan revman:
AÇIKLAMA
rev programı belirtilen dosyaları standart çıktıya kopyalar ve her satırdaki karakter sırasını tersine çevirir. Herhangi bir dosya belirtilmemişse, standart giriş okunur.
GÜNCELLEME:
dizenin uzunluğunu bilmiyorsanız, şunu deneyin:
$ x="lkj"
$ echo "${x%?}"
lk
Sed kullanarak bu kadar hızlı olmalı
sed 's/.$//'
Sizin tek yankı o zaman echo ljk | sed 's/.$//'.
Bunu kullanarak, 1 satır dize herhangi bir boyutta olabilir.
Kabuğa bağlı olarak birkaç seçenek:
t=${t%?}t=`expr " $t" : ' \(.*\).'`t=${t[1,-2]}t=${t:0:-1}t=${t:0:${#t}-1}t=${t/%?}t=${t/~(E).$/}@ {t=$1} ~~ $t *?Hepsinin son karakteri çıkarması gerektiğine dikkat edin, bazı uygulamaların (çoklu bayt karakterleri desteklemeyenlerin) bunun yerine son baytı soyduğunu görürsünüz ( eğer çoklu bayt olsaydı son karakteri bozabilir) ).
exprVaryantı varsayar $tbirden fazla satır karakteriyle bitmiyor. Ayrıca, sonuçta ortaya çıkan dizge bitmişse 0( 000veya hatta -0bazı uygulamalarda) sıfır olmayan bir çıkış durumu döndürür . Dize geçersiz karakterler içeriyorsa, beklenmeyen sonuçlar verebilir.
t=${t%?}Bourne değil , ancak bugünlerde bir Bourne kabuğuna rastlama ihtimaliniz yok. ${t%?}olsa diğerlerinde çalışır.
fishiş devam ediyor. 2.3.0.0.2005 - Binaya tanıtılan 2.3.0 stringsoru-cevap sırasında serbest bırakılmadı. Üzerinde test ettiğim sürümde ihtiyacınız olacak string replace -r '(?s).\z' '' -- $t(ve bunu değiştirmek isteyeceklerini umuyorum, PCRE'ye ilettikleri bayrakları değiştirmeleri gerekiyor) veya daha kıvrımlı olanları. Ayrıca yeni satır karakterleriyle de ilgileniyor ve bunu da değiştirmeyi planladıklarını biliyorum.
En taşınabilir ve en kısa cevap, neredeyse kesinlikle:
${t%?}
Bu bash, sh, kül, çizgi, busybox / kül, zsh, ksh, vb çalışır.
Eski okul kabuk parametresi genişlemesi kullanılarak çalışır. Spesifik olarak, glob kalıbıyla %eşleşen en küçük eşleşmeli parametrenin son ekini kaldırmayı belirtir.t? (yani: herhangi bir karakter).
(Daha fazla) daha ayrıntılı bir açıklama ve daha fazla arka plan için buradaki "En Küçük Ek Şablonunu Çıkarın" bölümüne bakın . Ayrıca, man bash"parametre genişletme" altındaki kabuğunuzun dokümanlarına bakın (örneğin :).
Not olarak, bunun yerine ilk karakteri kaldırmak isteseydiniz ${t#?},# dizenin önünden (önek) eşleşir (sonek).
Ayrıca değer belirterek hem olmasıdır %ve #var %%ve ##maç versiyonları, en uzun yerine kısa verili desen sürümünü. Her ikisi de ${t%%?}ve ${t##?}bu durumda tek operatörleri ile aynı şeyi yapacaktır, ancak (işe yaramaz ekstra karakter eklemeyin). Bunun nedeni verilen ?desenin sadece tek bir karakterle eşleşmesidir. Bir de karıştırın *olmayan bazı wildcard ile ve işler ile daha ilginç olsun %%ve ##.
Parametre genişlemelerini anlamak veya en azından onların varlığını bilmek ve nasıl görüneceğini bilmek, birçok lezzetin kabuk senaryolarını yazmak ve deşifre etmek için inanılmaz derecede faydalıdır. İyi ... onlar ... çünkü Parametre açılımları genellikle birçok kişiye oynamasından kabuk voodoo gibi bakmak vardır (eğer "parametresi genişleme" aramaya biliyorsanız oldukça iyi belgelenmiş olsa da) gizli kabuk büyü. Olsa da, bir kabuk takılı kaldığınızda kesinlikle alet kemeri içinde olması iyidir.
Ayrıca headson karakter dışındakilerin hepsini yazdırmak için de kullanabilirsiniz .
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Ancak ne yazık ki bazı sürümleri headlider -seçeneği içermemektedir . headOS X ile birlikte gelenler için durum bu.
Sadece bazı saf bash kullanımlarını tamamlamak için:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
İlk sözdizimi bir dizgeden bir alt dizgiyi alır, sözdizimi
İkincisi için, 'satırın sonundan' anlamına gelen işareti görür ve sözdizimi
${STRING:OFFSET:LENGTH} %
${STRING/PATTERN/SUBSTITUTION}
Ve burada yukarıda belirtilenlerin iki kısa şekli var
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
Burada yine, %en kısa eşleşen kalıbı (burada '' ile değiştir '), yani en kısa eşleşen kalıbı (burada, burada ' \ ' kaçış alanı ' ' ile gösterilir) PARAMETER'in sonundan - burada STR olarak adlandırılan işarete dikkat edin.