Awk kullanarak belirli bir sayıdan sonraki tüm sütunlar nasıl yazdırılır?


90

Kabukta, belirli bir sütuna ihtiyacım olduğunda awk'a gidiyorum.

Bu, sütun 9'u yazdırır, örneğin:

... | awk '{print $9}'

Awk'a sadece 9. sütunu değil, 9. sütunu da içeren ve sonraki tüm sütunları yazdırmasını nasıl söyleyebilirim ?


Yanıtlar:


83
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'

3
birkaç ufak düzeltme:awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'
glenn jackman

Teşekkürler @glenn, bu gerçekten biraz daha genel. Neyse - Ben kullanmak daha iyi olurdu kesinlikle kabul ediyorum cutya perlbunun için. Bunu yalnızca içeri almakta gerçekten ısrar ediyorsanız kullanın awk.
Amadan

1
@SiegeX: NUL bayt eklemez, FS'yi her boş alan arasında yerinde bırakır.
Dennis Williamson

1
Lütfen @ Ascherer'in zarafet cevabına bakın.

3
@veryhungrymike: Elegance güzel, ama doğru olmayı tercih ederim. : p
Amadan

68

Bir dizi alan yapmak istediğinizde, bunu yapmanın awkgerçekten kolay bir yolu yoktur. Bunun cutyerine şunu tavsiye ederim :

cut -d' ' -f 9- ./infile

Düzenle

Varsayılan sekme olması nedeniyle alan alanı sınırlayıcı eklendi. Glenn'e bunu işaret ettiği için teşekkürler


15
Cut ile ilgili bir şey, belirli bir sınırlayıcı (varsayılan olarak sekme) kullanmasıdır, burada awk "boşluk" kullanır. Kesik olarak, 2 ardışık sekme boş bir alanı sınırlar.
glenn jackman

1
@Glennjackman'ın belirttiği gibi, awk'ın ayırıcısı "boşluktur" (herhangi bir miktar da). Bu nedenle, kesme sınırlayıcısını tek bir alana ayarlamak da davranışla eşleşmez. ne yazık ki döngü yapabileceğiniz en iyi şey, bu yüzden görünüyor.
poncha

Bu düzgün çalışmıyor. Komutu dene find . | xargs ls -l | cut -d' ' -f 9-. Bazı nedenlerden dolayı çift boşluklar da sayılır. Örnek: lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_bsonuçlanacak./file_a 00:06 ./file_b
Marco Pashkov

@MarcoPashkov lütfen ortaya düzgün çalışmıyor Bu biri , özellikle kullandığınız dikkate tam da boru hattında aynı kodu. Bu arada, ls
SiegeX'in

Burada kesmek işi yapmaz. Örneğin, girişiniz bir satır için "foo bar" (tek boşluk) ve bir başkası için "foo ___ bar" (yani birden çok boşluk, ancak SO bunu gösteremeyecek kadar akıllıysa) ise, cut bunları farklı şekilde işleyecektir.
UKMonkey

54
awk '{print substr($0, index($0,$9))}'

Düzenleme : Not, dokuzuncudan önceki herhangi bir alan dokuzuncuyla aynı değeri içeriyorsa bu çalışmaz.


10
@veryhungrymike: ... ve dokuzuncudan önceki herhangi bir alan dokuzuncuyla aynı değeri içeriyorsa çalışmaz.
13:35 Amadan

6
Muhtemelen klasik cümle yüzünden "umarım dosyanızda bu sorun yoktur". Bu toplam var hayır-hayır : durumuna mühendislik s / w , 'biz kullanıcı bunları denemek değil akıllı yeterli olur çünkü "Biz, hata denetimi gibi negatif değerlerin girişi için dahil zaman israf etmeyeceğiz aracımızın çökmesi '". HAHAHA! Bunu her zaman duymayı seviyorum! Salaklar olarak (Ben mizah iyi bir anlamda gibi) Well, do var, onun şeyler yapmak için geliştirici görevim aptal geçirmez ! "İnsandaki iyiliği ummak" yerine. Bu daha ziyade filozoflardan beklenen bir tutum, s / w mühendisleri değil ... LOL
sözdizimi hatası

3
Hataları kontrol etmeyin demiyordum, ancak sorunla karşılaşmayacağınızı biliyorsanız, o zaman bu çözüm, belirttiğim gibi iyi. Ancak @ syntaxerror'a gereksiz olumsuz oy verdiğiniz için teşekkür ederiz. Bu çözüm, (şu anda) 19 olumlu oyların göstereceği gibi bazıları için işe yarayacak, ancak değilse, çözümünüz için kullanmayın. OP problemini çözmenin birçok yolu vardır.
Ascherer

1
Günlük işlerinizde komut satırında awk kullanıyorsanız, kesinlikle istediğiniz çözüm budur. Açık değil mi? Hata kontrolü, vb. Bu durumda gerçekten önemli değil çünkü siz yazıyorsunuz ve bu tür şeyleri enter tuşuna basmadan önce yakalayabiliyorsunuz (şahsen, awk'ın zaten başka bir şey için kullanılması gerektiğini düşünmüyorum, bu yüzden biz perl, python, tcl ve yaklaşık 100'den fazla başka, daha iyi, daha hızlı, daha az sinir bozucu betik dilleri var!) 'Tabii ki yazılım geliştiricilerime çok fazla kredi veriyorum ve yazdıkları şeylerde bile hata kontrolüne ihtiyaçları var anında (??)
osirisgothra

1
Cevabın hemen altında olduğu için buna ihtiyacı olduğundan değil, ama @atti'yi ekledim
Ascherer

11
sed -re 's,\s+, ,g' | cut -d ' ' -f 9-

Değişken genişlikteki boşluklarla uğraşmak yerine, tüm boşlukları tek boşluk olarak değiştirin. Ardından cutilgi alanlarıyla birlikte basit kullanın .

Awk kullanmıyor, bu yüzden alakalı değil ama diğer cevaplar / yorumlar göz önüne alındığında uygun görünüyordu.


1
Lütfen cevabınızı daha ayrıntılı hale getirin, aksi takdirde bunu soruya yorum olarak gönderin.
Alper Turan

Bu, ps faux | kullanım için idealdir . XYZ aracını kabul etmekten asla korkmayın, en uygun araç değildir.
kevinf

10

Genellikle perl awk / sed / grep et'in yerini alır. al. ve çok daha taşınabilir (aynı zamanda daha iyi bir çakı olduğu gibi).

perl -lane 'print "@F[8..$#F]"'

Elbette Timtowtdi geçerlidir.


Komut satırı seçeneği -leklemeniz veya \nprint ifadesine eklemeniz gerekir.
glenn jackman

@glenn jackman: Muhtemelen. Başka bir mesajın bir parçası veya bir değişkene atanmışsa gerekli değildir. "Daha iyi" olduğu sürece, perl kesinlikle küçükte daha iyi görünür. Büyük kuşkusuz çok dağınık görünebilir.
bobbogo

Beni yanlış anlamayın, Perl'den hoşlanıyorum. Gerçi ne olduğu için awk'ı seviyorum.
glenn jackman

Gömülü aygıtım Perl ile birlikte gelmiyor, ancak awk var.
Sepero

Olumsuz oylama çünkü soru bunun perl, ruby, java, python, bash değil awk dilinde nasıl yapılacağını sordu.
Tom Harrison

3
awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Bu, verilen alan N'den önce olanı keser ve Nr alanı da dahil olmak üzere satırın geri kalanının tamamını yazdırır ve orijinal aralığı korur (yeniden biçimlendirmez). Alan dizisinin satırın başka bir yerinde de görünmesi önemli değildir, bu Ascherer'in cevabındaki problemdir.

Bir işlev tanımlayın:

fromField () { 
awk -v m="\x01" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

Ve bunu şu şekilde kullanın:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost   

Çıktı, sondaki boşluklar dahil her şeyi korur N = 0 için tüm satırı olduğu gibi döndürür ve n> NF için boş dizeyi döndürür


Bu iyi bir fikir. Tipik bir gawk kullanan mevcut bir Mac'te pek çalışmıyor çünkü 0 $ çöküyor. Düzeltme, ilk adım olarak bir değişkeni $ 0 olarak ayarlamaktır, örneğin: '{s = $ 0; ... substr (s, index (s, m) +1}
yazdır

1

İşte bir ls -lçıktı örneği :

-rwxr-----@ 1 ricky.john  1493847943   5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john  1493847943  27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john  1493847943  21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john  1493847943  10627144 Apr 16 14:09 03-Where to Get Help.mp4

Baskı şey yazılan Benim çözüm $9olduğunuawk '{print substr($0, 61, 50)}'



0

İlk 3 alanı görüntülemek ve kullanabileceğiniz kalan alanları yazdırmak için:

awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename

$ 1 $ 2 $ 3 ilk 3 alandır.


0
function print_fields(field_num1, field_num2){
    input_line = $0

    j = 1;
    for (i=field_num1; i <= field_num2; i++){
        $(j++) = $(i);

    }
    NF = field_num2 - field_num1 + 1;
    print $0

    $0 = input_line
}

0

Awk yerine cut kullanmak ve -c karakter kesme komutunu kullanarak hangi sütundan başlayacağınızı bulmakla ilgili sorunları aşmak.

Burada diyorum ki, çıktının ilk 49 karakteri dışında hepsini ver.

 ls -l /some/path/*/* | cut -c 50-

/*/*/Ls komutunun sonunda çok alt dizinleri içinde ne göstermek beni söylüyor.

Ayrıca belirli karakter aralıklarını ala (cut man sayfasından) da çıkarabilirsiniz. Örneğin, şu anda oturum açmış kullanıcıların adlarını ve oturum açma saatlerini gösterin:

       who | cut -c 1-16,26-38
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.