Üçüncü sütunu son sütuna nasıl yazdırabilirim?


121

Bir DbgView günlük dosyasından (ilgimi çekmeyen) ilk iki sütunu kaldırmaya çalışıyorum. 3. sütundan itibaren satırın sonuna kadar yazdıran bir örnek bulamıyorum. Her satırın değişken sayıda sütun içerdiğine dikkat edin.


Yanıtlar:


108

... veya daha basit bir çözüm: cut -f 3- INPUTFILE sadece doğru sınırlayıcıyı (-d) ekleyin ve aynı etkiyi elde edersiniz.


9
Bunun yalnızca sınırlayıcı tüm sütunlar arasında tam olarak aynıysa işe yarayacağını unutmayın ... Örneğin, \ d + gibi bir sınırlayıcıyla kesme kullanamazsınız. (Bildiğim kadarıyla.)
Zach Wily

72
Soru awk olarak adlandırıldığında, awk dışında bir cevabı kabul etmek uygun değildir. Ya insanlar buna awk komut dosyaları için ihtiyaç duyarsa? Bu cevap sadece bir yorum olmalıydı.
syaz

24
@SyaZ: Normalde aynı fikirdeydim, ancak bu tahtadaki 'bedava awk' miktarı göz önüne alındığında, görevi yerine getirmenin alternatif bir yolunu göstermesi gerektiğini düşündüm. Biri size aynı görevi yapmanın daha basit ve daha hızlı bir yolunu gösterse minnettar olmaz mıydınız? Belki de, başka sorulara verilen 'yanlış değil, ancak kesinlikle geliştirilebilir' yanıtlarının sayısı nedeniyle bunu yapmanın tek yolunun awk olduğunu düşünen poster?
Marcin

12
Yorum bunun için. En iyi awk cevabını kabul edin ve yorumlar hakkında daha iyi non-awk önerileri sağlayın. İnsanlar sorulara tam olarak cevap vermeyen cevaplar göndermeye başlarsa, arama yapmak can sıkıcı olacaktır (benim durumumda).
syaz

12
Tüm sütunlar arasında yalnızca sınırlayıcı aynı olmak zorunda değildir, aynı zamanda sütunlar arasında TAM BİR sınırlayıcı karakter olmalıdır. Dolayısıyla, çıktılarını sınırlayıcılarla hizalayan programlarla uğraşıyorsanız, awk kullanmak daha iyidir.
sknaumov

112
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' daha kompakt olsun. :)
user172818

1
Teşekkürler lh3. Sadece gawk kılavuzunu kopyalayıp yapıştırıyordum. :)
Jonathan Feinberg

23
bu birden fazla satırla başarısız olur, her sütun yazdırıldığında yeni bir satır olarak değerlendirilir
meso_2600

13
Bölünmüş çıktı sorununu çözmek için şu çözümü öneriyorum: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfsatırsonu karakterini yazdırmayacak print "", diğer alanlar yazdırıldıktan sonra yeni satır ekleyecek)
lauhub

1
Veya: echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', veren: 3 4 5 6 7 8 9 10.
x-yuri

106

23
Bunun için biraz geç kaldım, ancak bu, birinci veya ikinci alanın üçüncüye eşit olduğu kayıtlar için işe yaramayacak (örneğin, 3 2 3 4 5)
aleph_null

dahili bir aralık yazdırmak da mümkündür: `` # 3 $ 'dan (dahil) 6 $' a (hariç); yankı "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {baskı substr ($ 0, dizin ($ 0, $ 3), uzunluk ($ 0) -dizin ($ 0, $ 6) -1)}'; # verir 3,4,5 "'
splaisan

34

Jonathan Feinberg'in cevabı her alanı ayrı bir satıra yazdırıyor. printfAynı satırdaki çıktı için kaydı yeniden oluşturmak için kullanabilirsiniz , ancak alanları bir sıçrayışla sola da taşıyabilirsiniz.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

1
Bunun yalnızca Gnu awk için çalıştığını NFunutmayın, POSIX tarafından azaltmaya izin verilmez.
kvantour

1
@kvantour: Gawk, mawk, MacOS awk (nawk?) ile çalışır. POSIX NF, azaltılıp azaltılamayacağı konusunda sessiz görünüyor .
sonraki duyuruya kadar duraklatıldı.


19
awk '{$1=$2=$3=""}1' file

Not: Bu yöntem 1,2,3 alanlarda "boşluklar" bırakacaktır ancak yalnızca çıktıya bakmak istiyorsanız bir sorun oluşturmaz.


Komutun izini sürmek için `| sed s / ^ \ * // | sütun -t` öndeki boşlukları çıkarmak ve kalan sütunları hizalamak için
MSpreij

Son ne anlama 1geliyor? hangi anahtar kelimeyle arama yapmalıyım awk?
Itachi


1
@Nathan sen bu sorunu {$1=$2=$3="";$0=$0;$1=$1}1
çözüyorsun

11

Aynı satırda örneğin 3'ten sonraki sütunları yazdırmak isterseniz, şunları kullanabilirsiniz:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

Örneğin:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

Yazdırılacak:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

Gördüğümüz gibi, maaş bordrosu boşlukla bile doğru satırda görünüyor.


Hızlı ve şık. Teşekkürler;)
9nz9

Bu harika, ancak $ NF'nin hariç tutulmasıyla ilgili bir sorunum var. Koşulu (<= NF) belirlediğimde son alanı alıyorum ama ilk alanın ilk karakteri kesiliyor. İşlevsellik açısından bir şeyi yanlış mı anlıyorum?
Ken Ingram

Görünüşe göre benim sorunum ^ M'nin son sütunun sonuna yapıştırılmış olması. Nasıl çıkarılacağını göremiyorum.
Ken Ingram

8

Aşağıdaki satıra ne dersiniz:

awk '{$ 1 = $ 2 = $ 3 = ""; print} 'dosyası

@ Ghostdog74 önerisine göre. Hatları filtrelediğinizde benimki daha iyi davranmalıdır, yani:

awk '/ ^ exim4-config / {$ 1 = ""; print} 'dosyası

Kısa ve basit. sed 's/\s\+//g'
Öndeki

8
awk -v m="\x0a" -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ırda başka bir yerde de görünmesi söz konusu değildir, daisaa'nın cevabındaki problem budur.

Bir işlev tanımlayın:

fromField () { 
awk -v m="\x0a" -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'nin kayıt ayırıcısı olduğu dosyalar için iyi çalışır, böylece satırların içinde yeni satır karakterine sahip olmazsınız. Diğer kayıt ayırıcılarla kullanmak istiyorsanız, şunu kullanın:

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

Örneğin. Onaltılık karakter nr kullanmadıkları sürece hemen hemen tüm dosyalarla iyi çalışır. Hatların içinde 1.


4

Aşağıdaki awk komutu, her satırın son N alanını ve satırın sonunda yeni bir satır karakteri yazdırır:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

Aşağıda / usr / bin dizininin içeriğini listeleyen ve ardından son 3 satırı tutan ve ardından her satırın son 4 sütununu awk kullanarak yazdıran bir örnek bulun:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype

4
awk '{a=match($0, $3); print substr($0,a)}'

İlk önce üçüncü sütunun başlangıcının konumunu bulursunuz. Substr ile, tüm satırı (0 $) konumundan başlayarak (bu durumda a) satırın sonuna kadar yazdıracaksınız.


3

Normal bir ifade kullanarak aynı etkiyi kolayca gerçekleştirebilirsiniz. Ayırıcının bir boşluk olduğunu varsayarsak, şöyle görünür:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
Normal ifadeden kaçınırım. Yanlışlıkla ortalığı karıştırmak muhtemelen daha yavaş ve daha kolaydır.
Cascabel

1
Şöyle kısaltın: awk '{ sub(/([^ ]+ +){2}/, ""); print }'Bu, deseni iki kez uzaklaştırır.
erik


2

Perl çözümü:

perl -lane 'splice @F,0,2; print join " ",@F' file

Bu komut satırı seçenekleri kullanılır:

  • -n girdi dosyasının her satırında döngü yapın, her satırı otomatik olarak yazdırmayın

  • -l işlemeden önce yeni satırları kaldırır ve daha sonra tekrar ekler

  • -aotomatik bölme modu - giriş satırlarını @F dizisine ayırın. Beyaz boşlukta bölmeye varsayılanlar

  • -e perl kodunu çalıştır

splice @F,0,2 @F dizisinden 0 ve 1 sütunlarını temiz bir şekilde kaldırır

join " ",@F her öğe arasında bir boşluk kullanarak @F dizisinin öğelerini birleştirir

Girdi dosyanız boşlukla sınırlı değil, virgülle ayrılmışsa, şunu kullanın: -F, -lane


Python çözümü:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file


1

Burada biraz geç, ama yukarıdakilerin hiçbiri işe yaramadı. Bunu deneyin, printf kullanarak her birinin arasına boşluk ekler. Sonunda satırsonu yazmamayı seçtim.

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'

1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

4. alandan başlayarak son alana kadar orijinal dosyadaki aynı sırayla kayıtları yazdırır


üzgünüm, bu tam olarak doğru cevap değildi. çok özel, ancak nasıl sileceğimi bilmiyorum
Massimo

1

Bash'de konumsal parametrelerle aşağıdaki sözdizimini kullanabilirsiniz:

while read -a cols; do echo ${cols[@]:2}; done < file.txt

Daha fazla bilgi edinin: Bash Hackers Wiki'de konumsal parametreleri yönetme


0

Yalnızca ilk iki alanı yok saymakla ilgiliyse ve bu alanları maskelerken boşluk istemiyorsanız (yukarıdaki bazı yanıtların yaptığı gibi):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

İlk iki sütun temizlenir, sedöndeki boşlukları kaldırır.


-2

AWK'da sütunlara alanlar denir, dolayısıyla NF anahtar

tüm satırlar:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

yalnızca ilk satır:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
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.