2016-03-26 18 views
1

Merhaba diyelim ki bir çift ismim var: , ve endeks numarasını almak istiyorum, bu durumda: 12, 124 ve 909. Genellikle, 'string range first last' alt dizinini ayıklamak için kullanabilirim. İlk ve sonuncuyu almak için 'string len orange' ve 'string len orange12' kullanacağım. Şimdi bunu yapmanın başka bir yolunu arıyorum.tcl: Dizeden numara almanın en kolay yolu?

'orange12'.split('orange')[1] 
'blue124'.split('blue')[1] 
'red909'.split('red')[1] 

Nasıl tcl böyle bir şey yapabilirsiniz:

Karşılaştırma olarak, Python, ben böyle bir şey yapabilir? Tcl'de 'split' denedim, ancak karmaşık görünüyor ve işe yaramazdı. Tcl'de bir kelime ile nasıl bölünebilirim (karakter değil)?

Teşekkür

cevap

6

biri Bazen scan en yararlı araçtır kullandı. Genellikle çok gözardı ediyor:

scan "green012" {%[a-z]%d} word num 
# $word is now “green” 
# $num is now “12” 
+0

Ve onu gözden kaçırdım. Evet ... bu benim regexp cevabım –

+0

dan daha iyi, bu harika. Ama daha fazla sorum var: eğer ihtiyacım olursa, 'kelime' ve 'num' değişkenlerine saklamak zorunda kalmadan, kelimenin veya num'in değerini döndürmek için 'tara'. Python betiğimde onliner işlevi olarak kullanılmasını istiyorum. örneğin, 'orange12' ile 'newname12' arasındaki ismi değiştirmek istiyorum. Şunun gibi bir şey yapmayı bekliyorum: newname [scan "orange12" {% d}], yani çıktı şu olmalıdır: newname12. Şu anda 'scan' komutu eşleşme sayısını – andio

+1

@andio olarak döndürecektir: try set newname [lindex [scan] orange12 "{% [az]% d}] 1]', veya daha iyisi 'set name [string] harita {orange newname} "turuncu12"]. –

2

Bu tam olarak ne beklediğiniz dize biçimi bağlıdır. Bilinen bir kelime (rakamsız) ise, örn. Bazı rakam takip 'turuncu', sözcüğü kaldırmak olabilir: sadece rakam gelen bir kelime olduğu biliniyorsa

% string map {orange ""} orange12 
12 
% string map {blue ""} blue124 
124 
% string map {red ""} red909 
909 

, normal bir ifade deneyebilirsiniz. Her halükarda, sayıların hala bir dize olarak temsil edildiğini unutmayın. Sıfır ile başlarsa, beklenmedik sonuçlara yol açabilecek sayısal biçime dönüştürüldüğünde sekizlik olarak yorumlanır.

Seçeneklerden biri scan içinden geçiyor:

% regexp {\d+} orange012 index 
1 
% puts $index 
012 
% expr 1*$index 
10 
% set index [scan $index %d] 
12 
% expr 1*$index 
12 

Düzenleme: Peter önerileri

+1

“regexp” değişkenlerini regexp -inline {\ d +} orange12' (dönüş değeri olarak verir) veya 'regexp {\ d +} orange12 endeksi '(biraz daha basit) düşünün. –

1

diğer cevaplar Tcl'de sorunu çözmek için, ancak yöneltilen soruyu cevaplamak için en iyi yolu göstermek, burada Tcl'de eşdeğer kod:

package require textutil 

lindex [textutil::splitx orange12 orange] 1 
lindex [textutil::splitx blue124 blue] 1 
lindex [textutil::splitx red909 red] 1 

textutil paketi, Tcl yardımcı kitaplığı olan Tcllib'un bir parçasıdır. splitx komutu, çekirdek komutunun split: splitx: dizgisi argümanının nerede ayrılacağını belirlemek için bir karakter kümesi yerine düzenli bir ifade alması için bir genişletme yedeğidir.

Dokümantasyon: lindex, textutil paket

+0

PS: Diğer metotlara ek olarak, "string trimleft $ s abdeglnoru" gibi bir şeyi de kullanabiliriz ('' 'renk-sayı dizgisini içerir), ama aslında bu oldukça aptalcadır. ;) –

0

nihayet burada paylaşmak istiyorum, benim kendi soru için en iyi yanıt bulmak i olmadan yapabilirsiniz

set name orange12345 
[scan $name [scan $name {%[a-zA-Z]}]%d ] 
#12345 

bilmek zorunda 'orange12' kelimesinden 'turuncu'. Bu nedenle kaynak adı şu şekilde bir rasgele isim olabilir: ANYNAMEanynumber. Örneğin, 'mywonderfulworld2345612' gibi bir ad.

+0

Yukarıdaki çözümlerin, kelimenin tam olarak ne olduğunu bilmesine gerek olmadığını unutmayın. Bu çözüm, 'scan' komutundan iki değer elde etmekten kurtulma denemesiyse, bu, yalnızca $ döndüren $ name {% * [a-zA-Z]% d} 'ile daha basit bir şekilde gerçekleştirilebilir. kelimenin ne olduğuna bakılmaksızın sayısal değer. –

+0

@PeterLewerin: Teşekkürler. harika çalışıyor. – andio