'Kes' komutunun, aynı sıralı sınırlayıcıları bir komutla işlemesi nasıl yapılır?


309

Sütun tabanlı, 'boşluk' ayarlı metin akışından belirli bir (dördüncü) alan ayıklamak çalışıyorum. cutKomutu aşağıdaki şekilde kullanmaya çalışıyorum :

cat text.txt | cut -d " " -f 4

Ne yazık ki, cutbirkaç boşluğa bir sınırlayıcı olarak davranmaz. Awk ile piped olabilirdi

awk '{ printf $4; }'

veya sed

sed -E "s/[[:space:]]+/ /g"

boşlukları daraltmak, ancak cutdoğal olarak başa çıkmanın herhangi bir yolu ve birkaç sınırlayıcı olup olmadığını bilmek isterim ?


12
AWK gidilecek yoldur.
sonraki duyuruya kadar duraklatıldı.

Yanıtlar:


546

Deneyin:

tr -s ' ' <text.txt | cut -d ' ' -f4

Gönderen tradam sayfası:

-s, --squeeze-repeats, yinelenen bir karakterin her girdi dizisinin yerini alır
                        SET1'de tek bir olayla listelenen
                        o karakterin

24
catBurada gerek yok. < text.txtDoğrudan adresine geçebilirsiniz tr. en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat
arielf

1
Bunun daha basit olduğundan emin değilsiniz, ancak birleşeceksiniz, kesimleri bırakıp -ddoğrudan birden çok karakterden sekmeye çevirebilirsiniz. Örneğin: Buraya who am i | tr -s ' ()' '\t' | cut -f5
Leo

Bu, awk çözümünün aksine, öncü / sondaki boşlukları (istenebilir veya istenmeyebilir, ancak genellikle değil) kaldırmaz. Awk çözeltisi de çok daha okunabilir ve daha az ayrıntılıdır.
n.caillou

-1 UYARI: BU SIRALI SINIRLAYICILARI TEK BİR TEDAVİYE ETMENİN AYNI DEĞİLDİR. Karşılaştırma echo "a b c" | cut -d " " -f2-,echo "a b c" | tr -s " " | cut -d " " -f2-
user541686

96

Sorunuza yorum yaptığınızda awk, gerçekten gitmek için bir yoldur. Kev'in cevabının gösterdiği gibi boşlukları sıkmak cutile birlikte kullanmak mümkündür .tr -s

Ancak gelecekteki okuyucular için olası tüm kombinasyonları gözden geçirmeme izin verin. Açıklamalar Test bölümünde bulunmaktadır.

tr | kesmek

tr -s ' ' < file | cut -d' ' -f4

awk

awk '{print $4}' file

darbe

while read -r _ _ _ myfield _
do
   echo "forth field: $myfield"
done < file

sed

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file

Testler

Bu dosya verildiğinde, komutları test edelim:

$ cat a
this   is    line     1 more text
this      is line    2     more text
this    is line 3     more text
this is   line 4            more    text

tr | kesmek

$ cut -d' ' -f4 a
is
                        # it does not show what we want!


$ tr -s ' ' < a | cut -d' ' -f4
1
2                       # this makes it!
3
4
$

awk

$ awk '{print $4}' a
1
2
3
4

darbe

Bu alanları sırayla okur. Bunu kullanarak _, bu alanları yoksaymak için "önemsiz değişken" olarak bir değişken değişken olduğunu belirtiriz. Bu şekilde, $myfieldaralarındaki boşluklar ne olursa olsun dosyada 4. alan olarak depolarız .

$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a
4th field: 1
4th field: 2
4th field: 3
4th field: 4

sed

Bu, üç boşluk grubunu yakalar ve birlikte boşluk bırakmaz ([^ ]*[ ]*){3}. Daha sonra, 4. alan olarak bir alana kadar gelen her şeyi yakalar ve sonunda yazdırılır \1.

$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4

2
awksadece zarif ve basit değil, aynı zamanda treksik olan VMware ESXi'ye de dahildir .
user121391

2
@ user121391 kullanmak için başka bir neden awk!
fedorqui 'SO' zarar vermeyi durdur '10

@fedorqui Ben hiç "önemsiz değişken" alt çizgi duymadım. Bu konuda daha fazla bilgi / referans sağlayabilir misiniz?
BryKKan

1
@BryKKan Greg'in öğrendim Bir dosyayı (veri akışı, değişken) satır satır (ve / veya alan-alan) nasıl okuyabilirim? : Bazı kişiler alanları atlamak için _ değişkenini "önemsiz değişken" olarak kullanır. readİçine ne girdiğini umursamıyorsak, (ya da aslında herhangi bir değişken) tek bir komutta birden fazla kez kullanılabilir . Bir şey olabilir, sadece bir şekilde yerine standart oldu junk_varya da whatever:)
fedorqui 'SO

25

en kısa / en samimi çözüm

Çok fazla sınırlamadan hayal kırıklığına uğradıktan sonra cut, cuts"steroidleri kesmek" için çağırdığım kendi yerine yazdım .

kesimler , buna ve diğer birçok ilgili kes / yapıştır problemineen minimalist çözüm olanı sağlar.

Bu özel soruyu ele alan birçok kişiden bir örnek:

$ cat text.txt
0   1        2 3
0 1          2   3 4

$ cuts 2 text.txt
2
2

cuts destekler:

  • dosyalardaki en yaygın alan sınırlayıcıların otomatik algılanması (+ varsayılanları geçersiz kılma yeteneği)
  • çok karakterli, karışık karakterli ve normal ifade eşlemeli sınırlayıcılar
  • karışık sınırlayıcılarla birden çok dosyadan sütun çıkarma
  • satır başına ek olarak satır sonu (negatif sayılar kullanarak) ofsetleri
  • sütunların otomatik olarak yan yana yapıştırılması ( pasteayrı olarak çağırmaya gerek yoktur )
  • alan yeniden siparişi için destek
  • kullanıcıların kişisel tercihlerini değiştirebilecekleri bir yapılandırma dosyası
  • kullanım kolaylığı ve minimalist gerekli yazım üzerine büyük önem

ve daha fazlası. Bunların hiçbiri standart olarak sağlanmamaktadır cut.

Ayrıca bakınız: https://stackoverflow.com/a/24543231/1296044

Kaynak ve belgeler (ücretsiz yazılım): http://arielf.github.io/cuts/


4

Bu Perl tek-astarı, Perl'in awk ile ne kadar yakından ilişkili olduğunu gösterir:

perl -lane 'print $F[3]' text.txt

Ancak, @Fawtos $F[0]alanları şununla başlarken autosplit dizisi dizinde başlar$1


3

cutBildiğim versiyonlarla , hayır, bu mümkün değil. cutöncelikli olarak, ayırıcının boşluk olmadığı (örneğin /etc/passwd) ve sabit sayıda alanı olan dosyaları ayrıştırmak için kullanışlıdır . Arka arkaya iki ayırıcı boş bir alan anlamına gelir ve bu boşluk için de geçerlidir.

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.