Kesim kesmediğinde ne kullanmalıyım?


19

Ben böyle bir dosya var cities:

[1598] San Diego, US (inactive)
[4517] St Louis, US (inactive)
[6346] Orlando, US (inactive)

Şehir adlarını kesmek istiyorum, böylece:

San Diego
St Louis
Orlando

Bu ben gelip en iyisi:

cut -d ',' -f1 cities | cut -d ']' -f2

Ama bu hala bana isimlerden önce bir boşluk bırakıyor. cutKesebilmem için birkaç karakterin sınırlayıcılarını kabul edebileceğim benzer bir komut var mı ]?


1
tristemediğiniz karakterleri silmek için kullanışlıdır.
LawrenceC

Kodu insanların yanıtlarında denerseniz, üç farklı çıktı görürsünüz. Bu, sorunuzun% 100 net olmadığını gösteriyor. "Kes", çıkarma veya seçme anlamına mı geliyor? (inactive)Durumu istiyor musun istemiyor musun ? Lütfen örnek çıktı sağlayın.
Mikel

@Mikel - Bir cutşeyleri kesmek için kullanıyorum ve sahip olduğum başarısız örneğin amacını görebildiğinizde, bağlamda oldukça açık olmalı. Ben daha fazla temizlemek için olsa örnek sağlayacaktır. :)
Kit Sunde

Hayır gerçek değil. Sorunuzdaki bir cümleyi "sadece şehir adlarını basmak" olarak değiştirdim, çünkü bu benim için belirsiz olan "kes" kelimesini kullanmanızdı. Değişikliğim doğru mu?
Mikel

1
@Kit Sunde: Örnek çıktı ile kesinlikle anlaşılabilir. Başlık sevimli. "Kes", Ctrl + X tuşlarına bastığınızda neler olduğunu düşünmemi sağlıyor, bu yüzden değişikliği önerdim, ama bu sizin sorunuz. Sadece basit bir anlaşmazlık olduğunda aşağı oylama aptalca olur.
Mikel

Yanıtlar:


15

Awk (ayrıca Awk Info'ya bakın ) bu tür bir soru ile güzeldir. Deneyin:

awk -F'[],] *' '{print $2}' cities

Bu alan ayırıcı tanımlar -Folarak [],] *sıfır ya da boşlukların herhangi bir sayıda ve ardından bir kapatma kare dirsek veya bir virgül bir oluşumunu, yani -. Elbette bunu herhangi bir gereksinime uyacak şekilde değiştirebilirsiniz. Düzenli ifadeleri okuyun.

Çizgi bölündükten sonra, bölünmüş sonuçla istediğinizi yapabilirsiniz. Burada, ikinci alanı sadece ile basmaya karar verdim print $2. Awk talimatları etrafında tek tırnak kullanmanın önemli olduğunu unutmayın, aksi takdirde 2 $ kabuk ile değiştirilir.


2
]bir köşeli ayraç değildir. Köşeli ayraçlar vardır <>. []"köşeli parantez" veya yalnızca "parantez" dir.
cjm

Normal ifadelerimi okumak zorunda kalmadıkça, kapanış ayraçından kaçmanız gerektiğini düşünüyorum.
Kit Sunde

@cjm - Belki de Almancadır: news.ycombinator.com/item?id=1181243 :)
Kit Sunde

1
@cjm, üzgünüm, köşeli ayraç demek istiyordum, biraz fazla hızlı yazdım. @Kit, Alman değilim. İç kapama braketinden kaçmak istemezsiniz (hiçbir amaca hizmet etmez), ancak aralıktaki ilk karakter olmalıdır.
asoundmove

12

cutBoru hattınızdaki sonuncuyu şu şekilde değiştirebilirsiniz :

cut -d ' ' -f2-

Yukarıdaki alan ayırıcı boşluk olduğu anlamına gelir ve biz ikinci alandan başlayarak tüm alanları seçmek istiyorum. Komple dizi:

cut -d ',' -f1 cities | cut -d ' ' -f2-

12

Daha karmaşık ayrıştırma için şunu kullanmalısınız: sed (1) :

sed -e 's/\[[0-9]\+\] \([^,]\+\),.*/\1/' cities

Veya pepoluan-r tarafından önerildiği gibi düzenli ifadeyi basitleştirmek için kullanarak :

sed -re 's/\[[0-9]+\] ([^,]+),.*/\1/' cities

2
+1. regex modelini büyük ölçüde basitleştiren gelişmiş regex karakterlerinden kaçınmak için -r'yi de kullanabilirsiniz
pepoluan

0

Normalde işler sed ve grep için çok zorlaştığında Perl kullanıyorum.

Perl'de yazmanın birkaç yolu vardır. Örneğin, hızlı olmasını tercih edebilirsiniz ya da girişte beklenmedik küçük problemlerle başa çıkmayı tercih edebilirsiniz (örneğin, beklenen iki boşluk).

Açık bir yol (kimliğin sayısal, şehir alfabetik, durum alfabetik olduğunu varsayar):

while (<>) {
    if (/^\[\d+\] (\w+(?: \w+)*), \w+ \(\w*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

Veya daha yavaş ama daha izin verici (daha fazla geri izleme yapar):

while (<>) {
    if (/^.*\]\s+(.*),.*$/) {
        my $city = $1;
        print "$city\n";
    }
}

Veya daha hızlı (alan kapanma braketinin ilk durağında durur):

while (<>) {
    if (/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/) {
        my $city = $1;
        print "$city\n";
    }
}

Komut dosyası yerine komut satırından -n, temelde while (<>) { BLOCK }döngüyü ekleyen seçeneği kullanabilirsiniz :

perl -ne '/^\[[^]]*\] ([^,]*), \S+ \([^)]*\)$/ and print $1, "\n";' cities

veya kullanımın kesime benzemesini istiyorsanız, -Fawk -Fseçeneğine benzer bir seçenek kullanabilirsiniz, örneğin:

perl -a -n -F'/[],]\s+/' -e 'print $F[1], "\n"' cities

Bu şekilde, hiçbir alanın herhangi bir sınırlayıcı içermeyeceği varsayılmaktadır.

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.