Kesme komutuyla alanı ayırıcı olarak kullanma


328

Boşluğu cutkomutla ayırıcı olarak kullanmak istiyorum .

Bunun için hangi sözdizimini kullanabilirim?


42
yanlış, kesim için man sayfası bunu açıklamıyor ve genel olarak bilgilendirici değil
UncleZeiv

2
Ayrıca, "bilgi kesme" bu durumda bir gelişme değildir.
cardiff space man

3
@ mklement0 hatırlıyorum, o zamandan beri silinmiş bir yoruma cevap veriyordum, ki bu soru, benim görüşüme göre "yanlış" olan adam sayfasında yanıtlandığı için reddediyordu, bunun için iyi bir neden olsa da ya da değil - şimdi, bu bilgi eksikliğinin iyi bir nedeni olabileceğine karar verirken, ortak kullanım örnekleri olmayan belgelerin, açıkça işe yaramazsa, en azından rahatsız edici olduğunu düşünüyorum
UncleZeiv

3
@UncleZeiv Anladım; açıklama için teşekkürler; bu soruya ilgi düşünüldüğünde, mansayfanın yeterli olmadığını varsaymak adil olur . Bir göz atalım: " Sekme karakteri yerine alan sınırlayıcı karakter olarak -d delimkullan delim." (BSD cut, ancak GNU sürümü ve POSIX spesifikasyonu hemen hemen aynı şeyi ifade eder). Bu nedenle, tipik bir durum olarak çağırmak için bir kabuk kullanmak, bir alanın, kabuk sayfası sözdizimini kullanarak argüman olarak genel olarakcut nasıl geçirileceğini bilmenizi gerektirir ; bu, muhtemelen man sayfasının işi değildir. Bununla birlikte, gerçek dünyadaki örnekler her zaman yardımcı olur ve GNU kılavuz sayfası bunlardan yoksundur. cut
mklement0

4
seçilen cevap teknik olarak doğru olmasına rağmen, @ mklement0 tarafından en yeni ve kapsamlı yanıtı standart yanıt olarak seçerek en üste süzülmesini sağlayın.
David LeBauer

Yanıtlar:


367
cut -d ' ' -f 2

Burada 2, istediğiniz boşlukla sınırlandırılmış alanın alan numarasıdır.


2
regEx'te olduğu gibi cut'un sınırlayıcı olarak belirli bir karakterin herhangi bir sayısını kullanmasını söyleyebilir misiniz? ör. herhangi bir sayıda alan, ör. \ s +
ampütan

3
@ foampile Hayır, yapabileceğine inanmıyorum.
Jonathan Hartley

6
Sen ile Regexes kullanamazsınız cut, ama sen ile cuts"düzeltme" için hangi çalışır her cutsınırlamaları: github.com/arielf/cuts
arielf

alan sınırlaması olan her üçüncü alanı alabilir misiniz? gibi cut -d ' ' -f 3,6,9,12,15,18her sayısını belirtmek zorunda kalmadan?
Monocito

169

Genellikle boşluğu sınırlayıcı olarak kullanırsanız, bazı sütunları boşluklarla hizalayan bir komutun çıktısını ayrıştırdığınız için birden çok boşluğu bir olarak ele almak istersiniz. (ve bunun için google araması beni buraya getiriyor)

Bu durumda tek bir cutkomut yeterli değildir ve kullanmanız gerekir:

tr -s ' ' | cut -d ' ' -f 2

Veya

awk '{print $2}'

2
Awk örnek kullanımı için teşekkürler, tam da ihtiyacım olan şey.
spazm

44

Mevcut, yardımcı cevapları tamamlamak için; Ayrı bir cevap göndermem konusunda beni teşvik ettiği için şapkanın QZ Destek bölümüne ipucu :

Burada iki farklı mekanizma devreye giriyor:

  • olup, (a) cut kendisine iletilen (bu durumda alanı) sınırlayıcı gerektiren -dseçenek bir olduğu ayrı bir argüman ya da ekler için kabul edilebilir olup olmadığı , doğrudan için -d.

  • (b) kabuğun argümanları genellikle çağrılan komuta iletmeden önce nasıl ayrıştırdığı.

(a) kamu hizmetleri için POSIX yönergelerinden bir alıntı ile cevaplanır (benimkini vurgulayın)

Standart bir yardımcı gösterir ÖZET bir ile bir seçenek ise , zorunlu bir seçenek-değişken [...] bir uygun uygulama kullanmak zorundadır ayrı bu seçenek ve seçenek-değişken için bağımsız değişkeni . Ancak , bir uygun uygulama olacaktır da karakterleri müdahale olmadan aynı argüman dizesinde seçeneği ve seçenek-argüman belirtmek etmelerine izin vermek .

Başka bir deyişle: Bu durumda, çünkü -dbireyin seçenek-argümanı zorunlu , şunları yapabilirsiniz seçim sınırlayıcı olarak belirtmek ister :

  • EITHER: ayrı bir tartışma
  • (d) VEYA: doğrudan bağlı-d bir değer olarak .

(S) veya (d) 'yi seçtikten sonra, kabuğun dize değişmez ayrıştırma - (b) - önemlidir:

  • Yaklaşım (lar) ile aşağıdaki formların hepsi EŞDEĞER:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • (D) yaklaşımıyla , aşağıdaki formların hepsi EŞDEĞERDİR:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Eşdeğerlik, kabuğun string-literal işlemesi ile açıklanmaktadır:

Tüm içinde sonucunda Yukarıdaki çözümler aynı dize zaman (her grupta) cutonları görür :

  • (ler) : cutgörür -donun gibi kendi bir takip argüman, ayrı bir uzay karbonlaşmış madde içeren argüman - tırnak veya olmadan \öneki !.

  • (d) : artı bir boşluk karakteri cutgörür - tırnak işaretleri veya önek olmadan ! - aynı argümanın bir parçası olarak .-d \

İlgili gruplardaki formların sonuçta özdeş olmasının nedeni, kabuğun dize değişmezlerini nasıl ayrıştırdığına bağlı olarak iki yönlüdür :

  • Kabuk belirtilmesi hazır sağlar olduğu gibi boyunca adı verilen bir mekanizma alıntı sunar, çeşitli formları :
    • tek tırnaklı dizeler: içerideki içerik tam anlamıyla'...' alınır ve tek bir argüman oluşturur
    • çift ​​tırnaklı dizeler: içerideki içerikler "..."de tek bir argüman oluşturur, ancak enterpolasyona tabidir ( $varkomut ikameleri ( $(...)veya `...`) veya aritmetik açılımlar ( $(( ... ))) gibi değişken referanslarını genişletir .
    • \arasında -quoting ayrı karakterler : bir \tek karakteri, önceki karakter hazır olarak yorumlanmalıdır neden olur.
  • Alıntı, tırnak işareti kaldırılarak tamamlanır , yani kabuk bir komut satırını ayrıştırdıktan sonra tırnak karakterlerini bağımsız değişkenlerden (çevreleyen veya veya örnekler) kaldırır - dolayısıyla, çağrılan komut tırnak karakterlerini asla görmez .'...'"..."\

36

Ayrıca şunları da söyleyebilirsiniz:

cut -d\  -f 2

Ters eğik çizgiden sonra iki boşluk olduğunu unutmayın.


30
Bir sonraki karakterden kaçtığını bilen kişi, bir sonraki karaktere dikkat etmek için çok dikkatli olacaktır. Bunun gibi boşluk karakterlerinden kaçmak için '\' kullanmak çok yaygın bir deyimdir.
Jonathan Hartley

3
@Jonathan Hartley genellikle kodların çoğu gerçekten okunamıyor :)
Luca Borrione

1
Linux / unix açısından \ benim ilk denememdi ve işe yaradı. Buna kıyasla daha az belirgin olduğunu kabul ediyorum ' ', ancak eminim ki birçoğu bunu davranışların güvencesi olarak okumaktan mutluluk duyuyor. Daha iyi anlamak için lütfen aşağıdaki @ mklement0'ın yorumuna bakın.
tresf

@JonathanHartley düzeltmesi: "bir sonraki karakterden kaçtığını bilen bencil kişi ve bunu herkesin bildiğini varsayar ". Kişisel projeler için bu geçerli değildir, ancak bir takım ortamında bu varsayım çok tehlikeli (ve potansiyel olarak maliyetli) bir varsayımdır.
Eduard Nicodei

1
@EduardNicodei Oh katılıyorum. Kodun okuyucuları hakkında konuşuyorduk ("kim fark eder ...?"), Yazarlardan değil. Ama aynı zamanda, bazı takımlarda belli bir yeterlilik seviyesine sahip olmak iyidir. Çevreye bağlıdır.
Jonathan Hartley

5

Ben sadece keşfetti de kullanabileceğiniz "-d ":

cut "-d "

Ölçek

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am

1
Gerçekten - ya da '-d '.
mklement0

3
Not olduğu gelen cuts' perspektif bütün aşağıdakilerden aynıdır: "-d ", '-d ', -d" ", -d' ', ve -d\<space>: seçeneğiyle (doğrudan ekleme tüm formların seçenek argümanı (boşluk) -diçinde) ve sonucu tam aynı dize zaman cutonları görür: Tek kabuk alıntı kaldırma
mklement0

1
@ mklement0 cevabı olmalıdır cevap. Bu sayfadaki en kapsamlı olanıdır (bir yorum olsa bile).
tresf

@ QZSupport: Duyguyu ve teşviki takdir ediyorum - kendi cevaplarımı ek arka plan bilgileriyle göndermeme ilham verdi.
mklement0

1
Lol büyüleyici keşif!
Harry

4

Verilerde örneğin birden fazla boşluk varsa bunu kesim ile kolayca yapamazsınız. Daha kolay işlem için girişi normalleştirmeyi yararlı buldum. Bir numara normalleştirme için sed'i aşağıdaki gibi kullanmaktır.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar

3

scut , herhangi bir perl regex'i kırma jetonu olarak kullanabilen kesilmiş benzeri bir yardımcı program (daha akıllı ama daha yavaş yaptım) Boşluktan ayırma varsayılan değerdir, ancak çoklu karakter regex'lerini, alternatif regex'leri vb.

scut -f='6 2 8 7' < input.file  > output.file

bu nedenle yukarıdaki komut boşlukta sütunları kırar ve (0 tabanlı) 6 6 8 7 numaralı sütunları bu sırayla çıkarır.


0

sedDüzenli ifadeleri ve yakalama gruplarını içeren bir cevabım var (biraz kafa karıştırıcı cevabı itiraf ediyorum) :

  • \S* - İlk kelime
  • \s* - sınırlayıcı
  • (\S*) - ikinci kelime - ele geçirilmiş
  • .* - hattın geri kalanı

Bir sedifade olarak, yakalama grubunun kaçması gerekir, yani \(ve \).

\1Döner yakalanan grubunun bir kopyası, ikinci kelime yani.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Bu cevaba baktığınızda, biraz kafa karıştırıcı ve düşünebilirsiniz, neden rahatsız oluyorsunuz? Bazılarının "Aha!" ve bu kalıbı tek bir sedifadeyle karmaşık metin çıkarma problemlerini çözmek için kullanacaktı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.