Python dizesi hazır bilgisini ayrıştırma


9

Meydan etmektir Python yaptığı gibi bir dize ayrıştırmak ve dize içeriğini yazdırın.

  • Girdi (komut satırı bağımsız değişkeni veya stdin) : bir dize değişmezi (ör. "hello") (Veya birden çok değişmez, aşağıdaki dize değişmez değer birleştirmesine bakın)
  • Çıktı (stdout) : dizenin içeriği (ör. hello)

Dizeyi ayrıştırma kuralları:

  • Bir dizgi değişmezi eşleşen tek tırnak ( 'a'), çift tırnak ( "a"), üçlü tek tırnak ( '''a''') veya üçlü çift tırnak ( """a""") çiftleri içine alınır . Dizeyi açan tırnak türünün ilk tekrarlaması dizeyi bitirir.
  • Ters eğik çizgi kaçar: \' bir dize içinde olur ', \"olur "ve \\olur \. Başka ters eğik çizgi kaçışları uygulamanız gerekmez. Bir kaçış dizisinin parçası olmayan bir ters eğik çizgi ters eğik çizgi olarak kalır.
  • Dize değişmezi bitiştirmesi: Bitişik dize değişmezlerinin içerikleri birleştirilir. Örneğin, "hello" 'world'olur helloworld.
  • Girdi, hiçbir değişmez değerin parçası olmayan boşluklar içerebilir.
  • Değişmez değerler içinde veya dışında başka herhangi bir beyaz alanı desteklemenize gerek yoktur.

Ek kurallar:

  • eval, execVe benzeri şeyler izin verilmez literal veya bazı kısımlarını ayrıştırmak için.
  • Girişin geçerli olduğunu varsayabilirsiniz.
  • Maksimum giriş uzunluğu 1023 karakter olabilir.

Örnekler:

  • "hello" ' world' -> hello world
  • """\"""'\\\A""" -> """'\\A
  • ( '''"""'''"""'''""" ) (parantez olmadan, ancak boşluklarla) -> """'''

En kısa kod kazanır.


Çıktı depolanabilecek bir formda mı yoksa yazdırmak ve onunla yapılması yeterli mi?
DavidC

@David Baskı yapmanız gereken tek şey.
flornquake

Yani (örneğin) "\ z" de, kod ters eğik çizgi ve z? Ancak çift tırnak işaretleri veya üçlü tırnak işaretleri içinde görünse bile, kesme işareti olur mu? Bu doğru mu?
ekmek kutusu

@breadbox Kesinlikle.
flornquake

Kod ham dizeleri desteklemeli mi? Ham olmayan ve ham dizelerin birleştirilmesine ne dersiniz?
Bakuriu

Yanıtlar:


4

Perl, 54 karakter

#!/usr/bin/perl -p
s/ |("""|'''|"|')((\\?.)*?)\1/$2/g;s/\\(["'\\])/$1/g

Bunu yayınlarken, Jan Dvorak'ın Ruby çözümüyle neredeyse aynı olduğunu fark ettim. Aslında bunun ne kadar benzer olduğuna biraz dayayım ama "Büyük beyinler benzer düşünür" diyeceğim ve bırakalım.

Bu program Perl betiklerindeki karakterleri saymada garip bir köşe vakasını vurgular: Okuduğumda, koddaki tek tırnakların varlığı -pseçeneği toplamıma doğru iki karakter olarak saymam gerektiği anlamına gelir . Tipik olarak, Perl komut dosyası boyutlarını hesaplarken, seçeneklerdeki ilk tire karakterinin -e, programı uygun şekilde tanıtan programla birlikte paketlenebileceği gerekçesiyle ücretsiz olduğu kabul edilir ... ancak daha sonra ekstra kaçışları da hesaba katmalısınız komut dosyasını komut satırına girmeniz gerekir. Tek tırnak çok kaçan gerektirir, bu yüzden ceza önlemek için bir dosyadan çalıştırılan bir komut dosyası olarak saymak zorunda ve bu nedenle ben #!/usr/bin/perlücretsiz olsun , ancak herhangi bir seçenek karakter. Biraz kafa karıştırıcı.


2
Farklı olmak istiyorsanız (('|")\2{2}?), aynı uzunluktadır("""|'''|"|')
Peter Taylor

3

C, 178 karakter

char*p,*q,b[1024];d;main(t){for(p=q=gets(b);*p=*q++;)
d?*p==92&!(*q-*p&&*q-34&&*q-39)?*p++=*q++:*p-d||t&&*q-d|q[1]-d?++p:
(d=0,q+=2*t):*p-32?d=*p,t=*q==d&q[1]==d,q+=2*t:0;puts(b);}

Bu, her şeyin üçlü operatör zinciri çetesinin içinde yapıldığı C çözümlerinden biridir.

Program, karakterleri aynı ara belleğe kopyalayarak, metakarakterlerin üzerine yazarak çalışır. dbir dizenin içindeyken ayırıcıyı tutar ve ayırıcı tüçlü bir tırnaksa doğrudur.


Döngü kontrol değişkeninin koşullu ekstra artışını eklemeniz gerektiğini düşünüyorum. 'Foo \\' bar 'için, \\ \' nin yerine geçer gibi görünen foo \ ar 'verir, ancak daha sonra yeni girilen \' ile ayrıştırmaya devam eder, bir sonraki belirteci \ 'olarak görür.
manatwork

Aslında, bu örnek geçersiz girdi. 'foo\\'"foo" dizesini belirtir, bunu boşluk veya dize sınırlayıcı olmayan bir karakter izler.
breadbox

Hata. Bu kuralı yanlış okudum. O zaman elbette kodunuz doğrudur.
manatwork

3

Yakut, 74 73 karakter

puts gets.gsub(/('''|"""|'|")((\\?.)*?)\1|./,'\2').gsub /\\([\\'"])/,'\1'

Buradaki çekirdek iki regex'tir: Birincisi dize sınırlarını belirler ve sadece içeriği seçer. Değişiklik, dizelerin içinde olmayan her şeyi kaldırmak için var ve ayrıca kapatılmamış dizeleri de düşürüyor.Ters eğik çizgiler, isteğe bağlı-isteğe bağlı olarak kabul edilir ve bunu bir şey izler. Böylece,(\\?.)Normal ifade motoru geçerli girişler için geri adım atmayacağından (teşekkürler @breadbox), tek bir ters eğik çizgi orada eşleşemez. Teklifler tembel tekrarlama ile ele alınır. İkinci normal ifade daha sonra her kaçan karakterden önce bir ters eğik çizgi çizer. Normal ifade, her zaman önce en soldaki alternatifi seçmek için motora bağlıdır.

Ayrıca bir devlet-makine yaklaşımı olarak da düşündüm, ancak normal ifade çözümüne kıyasla oldukça büyük (19 eyalet x 4 karakter sınıfı) ortaya çıktı. Herkes ilgileniyorsa hala devlet makinesini gönderebilirim.


Bu yöntemle bir küçük aksaklık: 'foo \' bar 'yerine' foo \\ 'bar' foo \ olur.
manatwork

@manatwork biçimlendirmede bir şey kaybolmadıkça bu doğrudur. İlk ters eğik çizgi ikincisinden kaçar. 'foo\\'ilk dizedir ve bar'girdi olduğunda dize bağlamının dışındadır'foo\\'bar'
John Dvorak

Hata. Daha önce nasıl hesapladığımı bilmiyorum. Tabii ki doğru. Afedersiniz.
manatwork

Bunu çalıştırmaya çalıştığımda bir hata iletisi alıyorum: "nested *? + İn regexp". İhtiyacım olan minimum sürüm veya çalışma zamanı bayrağı var mı?
Ekmek kutusu

@breadbox Diğer sürümleri kontrol etmedim, ama yakut 1.9.3 (JRuby 1.7.2) kullanıyorum. en az 1.9.3 varsaymalı ve bunu düzenlemeli miyim?
John Dvorak
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.