bash: n'inci sütun çıktısını almanın en kısa yolu


166

Diyelim ki iş gününüzde bash'daki bazı komutlardan aşağıdaki şekilde tekrarlanan aşağıdaki sütun formlu çıktıyla karşılaşıyorsunuz (benim durumumda svn stRails çalışma dizinimde yürütmekten ):

?       changes.patch
M       app/models/superman.rb
A       app/models/superwoman.rb

komutunuzun çıktısı ile çalışmak için - bu durumda dosya adları - bir tür ayrıştırma gereklidir, böylece ikinci sütun bir sonraki komut için girdi olarak kullanılabilir.

Ne yapıyorum awkikinci sütun almak için kullanmaktır , örneğin tüm dosyaları (tipik bir usecase bu :) kaldırmak istiyorum, ben yapardı:

svn st | awk '{print $2}' | xargs rm

Bunu çok yazdığımdan, doğal bir soru şudur: bunu bash'da yapmanın daha kısa (böylece daha soğuk) bir yolu var mı?

NOT: Sorduğum şey, somut örneğim svn iş akışımda olmasına rağmen aslında bir kabuk komut sorusudur. Eğer iş akışının aptalca olduğunu düşünüyorsanız ve alternatif bir yaklaşım öneriyorsanız, muhtemelen size oy vermeyeceğim, ancak diğerleri olabilir, çünkü buradaki soru gerçekten n. Sütun komut çıkışını mümkün olan en kısa şekilde nasıl elde edeceğinizdir. . Teşekkürler :)


1
Bir komutu sık sık kullandığınızda, bir komut dosyası oluşturup yolunuza koyabilirsiniz. İsterseniz bashrc'nizde bir işlev oluşturabilirsiniz. Sütun seçimi ifadesini azaltma noktasını görmüyorum.
Lynch

1
Haklısın, ben de yapabilirim. 'Nokta' öğrenme amacıyla, ama çoğunlukla eğlence için bash şeyler yapmak için yeni yollar
arayışıdır

1
Ayrıca bir yere ssh yaparken .bashrc'niz yok, bu yüzden onsuz yolunuzu bilmek yararlıdır.
Kos

Yanıtlar:


125

cutİkinci alana erişmek için kullanabilirsiniz :

cut -f2

Düzenleme: Üzgünüz, SVN'nin çıktısında sekme kullanmadığının farkında değildi, bu yüzden bu biraz işe yaramaz. Çıktıya uyarlayabilirsiniz cut, ancak biraz kırılgan - cut -c 10- işe yarayacak bir şey , ancak kesin değer kurulumunuza bağlı olacaktır.

Başka bir seçenek şudur: sed 's/.\s\+//'


1
Çıktı cut -f2ile birlikte kullanmayı deneyin svn st. Görmediğini göreceksin.
Lynch

Gerçek svn stçıktısında sekmeler kullanacağını varsaydım . Bazı testlerden sonra durum böyle değil. Lanet olsun.
pores

21
-dBunun çalışmasına izin vermek için uygun bir sınırlayıcı geçmek .
Yogh

6
@Yogh'un söylediklerini genişletmek için, sınırlayıcı olarak boşluklar için, bu gibi görünecektir cut -d" " -f2.
adamyonk

Stdout üzerinde awk olmadan xargs kullanın: svn st | xargs | kes -d "" -f2
vr286

106

Aynı şeyi başarmak için:

svn st | awk '{print $2}' | xargs rm

sadece bash kullanarak şunları kullanabilirsiniz:

svn st | while read a b; do rm "$b"; done

Verilen, daha kısa değil, ama biraz daha verimli ve dosya adlarınızdaki boşlukları doğru bir şekilde işliyor.


Nedir ave bnasıl alınır?
Timo

1
@Timo ailk sütunu ve bkalan sütunları temsil eder. İkinci sütunu yazdırmak istiyorsanız, yerine kullanın read a b c;ve kullanın . Bunu bir grep paterni izleyen bir dizi kimlik almak için kullandım, böylece hepsini kesebilirim. echorm
Matt Kleinsmith

37

Kendimi aynı durumda buldum ve bu takma adları dosyama ekledim .profile:

alias c1="awk '{print \$1}'"
alias c2="awk '{print \$2}'"
alias c3="awk '{print \$3}'"
alias c4="awk '{print \$4}'"
alias c5="awk '{print \$5}'"
alias c6="awk '{print \$6}'"
alias c7="awk '{print \$7}'"
alias c8="awk '{print \$8}'"
alias c9="awk '{print \$9}'"

Hangi böyle şeyler yazmama izin veriyor:

svn st | c2 | xargs rm

15
Bash fonksiyonları genellikle daha kullanışlıdır. Bunu yaptım: function c() { awk "{print \$$1}" } O zaman şunları yapabilirsiniz: svn st | c 2 | xargs rm
Aissen

8
Ama sonra fazladan bir alan yazmam gerekiyor. Çok yorucu :)
StackedCrooked

16

Zsh'i deneyin. Son ek takma adını destekler, böylece .zshrc'nizde X'i tanımlayabilirsiniz

alias -g X="| cut -d' ' -f2"

o zaman şunları yapabilirsiniz:

cat file X

Bir adım ileri gidebilir ve n. Sütun için tanımlayabilirsiniz:

alias -g X2="| cut -d' ' -f2"
alias -g X1="| cut -d' ' -f1"
alias -g X3="| cut -d' ' -f3"

"file" dosyasının n. sütununu çıktılar. Bunu grep çıktısı veya daha az çıktı için de yapabilirsiniz. Bu çok kullanışlı ve zsh'ın katil bir özelliği.

Bir adım daha ileri gidebilir ve D'yi şu şekilde tanımlayabilirsiniz:

alias -g D="|xargs rm"

Şimdi yazabilirsiniz:

cat file X1 D

"file" dosyasının ilk sütununda belirtilen tüm dosyaları silmek için.

Eğer bash'ı biliyorsanız, zsh bazı yeni özellikler dışında bir değişiklik değildir.

HTH Chris


ahh, yukarıdaki yorumumu yazarken cevabınızı güncellediğinizi görüyorum :) Bir şekilde dinamik olarak hangi sütunu alacağınızı belirtebilir misiniz, yoksa .zshrc'de n-satırlara ihtiyacım var mı (bu önemli değil, sadece meraklı)
sv1

Yazımı daha fazla düzenledim ve dosyaları silmek için bir "D" soneki tanımladım. Bildiğim kadarıyla her son ek için bir satır eklemek zorunda kalacak.
Chris

Veya X komutunun ilk parametresi yapın. Bunların hiçbiri zsh veya takma ad gerektirmez, belki de tuhaf bir takma adı takma fikri hariç.
Üçlü

1
Neden hepinizin bu cutseçeneği sevdiğini anlamıyorum . Sadece çıktısını kullanarak makinemde çalışmıyor svn st. svn st | cut -d' ' -f2Sadece ne olduğunu görmeye çalışın .
Lynch

@ Sv1, takma adı tanımlamak için bir döngü yazabilirsiniz, çünkü takma ad sadece bir komuttur.
sürüklenme avcısı

8

Senaryolara aşina olmadığın için işte bir örnek.

#!/bin/sh
# usage: svn st | x 2 | xargs rm
col=$1
shift
awk -v col="$col" '{print $col}' "${@--}"

Bu tasarruf Eğer varsa ~/bin/xve emin ~/binGözlerinde farklı olduğunu PATH(şimdi o sizin ve koymak gerekir bir şeydir .bashrcgenellikle sütun n ayıklanması için en kısa komut var); x n.

Komut dosyası, sayısal olmayan bir bağımsız değişken veya yanlış sayıda bağımsız değişken, vb. İle çağrılırsa uygun hata denetimi ve kefalet işlemlerini gerçekleştirmelidir; ancak bu çıplak kemiklerin temel versiyonunu genişletmek ünite 102'de olacak.

Belki de betiği farklı bir sütun sınırlayıcıya izin verecek şekilde genişletmek istersiniz. Awk varsayılan olarak boşluktaki alanlara girişi ayrıştırır; farklı bir sınırlayıcı kullanmak için yeni sınırlayıcının -F ':'nerede :olduğunu kullanın . Bunu betiğe bir seçenek olarak uygulamak biraz daha uzun sürer, bu yüzden bunu okuyucu için bir egzersiz olarak bırakıyorum.


kullanım

Bir dosya verildi file:

1 2 3
4 5 6

Ya stdin ile iletebilirsiniz ( işe yaramazcat bir şey için sadece daha yararlı bir şey için bir yer tutucu olarak );

$ cat file | sh script.sh 2
2
5

Veya senaryoya argüman olarak sağlayın:

$ sh script.sh 2 file
2
5

Burada, sh script.shkomut dosyasının script.shgeçerli dizinde olduğu gibi kaydedildiği varsayılmaktadır ; bunu sizin içinizde bir yerde daha kullanışlı bir adla kaydeder PATHve yukarıdaki talimatlarda olduğu gibi yürütülebilir olarak işaretlerseniz, bunun yerine yararlı adı kullanın (ve hayır sh).


Güzel fikir, ama sh veya bash olduğu gibi benim için pek çalışmıyor. Bu çalışıyor: #! / Bin / bash col = 1 $ vardiyalı awk "{print \ $$ col}"
mgk

Bu geç yorum için teşekkürler. Düzeltmenizle güncellendi.
tripleee

1
daha iyiawk -v col=$col ...
fedorqui 'SO

@fedorqui Geri bildiriminiz için teşekkür ederiz, burada ve başka yerlerde! Yanıt güncellendi. Şimdi biraz daha uzun olduğundan, sahip olabileceğiniz en kısa komut dosyasını istiyorsanız , orijinal sürümün düzeltme geçmişine bakın .
tripleee

1
@fedorqui Teşekkürler! catHisterik nedenlerden dolayı örneğe küçük bir uyarı eklendi (-:
üçlü

5

Zaten bir çözümünüz var gibi görünüyor. İşleri kolaylaştırmak için, neden komutunuzu bir bash komut dosyasına (kısa adla) koymuyorsunuz ve her seferinde bu 'uzun' komutu yazmak yerine çalıştırmıyorsunuz?


Bence onun 'serin' değil bence. Neden? Aslında .bashrc dosyamı bunu yapan ve kısaca bir meta-kabuk yazan çeşitli kısayollarla doldurmak istemiyorum. Olduğu gibi oldukça takma. Bunu söyledikten sonra öneriniz kötü değil.
Sv1

2
.bashrc? Neden bash ile ilgili olmayan şeylerle karıştırıyorsunuz? Yaptığım her komut kümesi için ayrı komut dosyaları yazmak ve hepsini bir ~/scriptsdizine koymak . Sonra bütününü eklemek ~/scriptskardeşime karşı PATHİhtiyacım olduğunda ben sadece adıyla onlara ulaşabilmesi için.
Tarek Fadel

4
Sonra .bashrc içine koymayın. ~ / Bin içinde bir komut dosyası oluşturun ve PATH'nizde olduğundan emin olun.
üçlü

2

Sütunu manuel olarak seçmeyi tercih ediyorsanız, pick tuşunu kullanarak çok hızlı olabilirsiniz :

svn st | pick | xargs rm

2. sütunun herhangi bir hücresine gidin, tuşuna basın cve ardındanenter


Başvurduğunuz "çekme" aracını denedim ve çok beğendim. Seçilen sütunları yazdırmak istediğim, ancak yalnızca istediğiniz sütunu almak için "awk '{print $ 3}'" yazmak istemediğim birçok durum için çok iyi. Ne yazık ki, ad daha popüler gibi görünen farklı bir "çekme" aracıyla çakışıyor - "apt install pick" ile kurulabilir. Bu yüzden aracınızı, sistemimdeki "yakalama" olarak yeniden adlandırdım ve kullanmaya devam etmeyi planlıyorum. Referans gönderdiğiniz için teşekkür ederiz.
William Dye

1

Bu dosya yolunun svn st çıktısının ikinci sütununda olması gerekmez. Örneğin, dosyayı değiştirirseniz ve özelliğini değiştirirseniz, 3. sütun olur.

Olası çıktı örneklerine bakınız:

svn help st

Örnek çıktı:

 M     wc/bar.c
A  +   wc/qax.c

İlk 8 karakteri şu şekilde kesmenizi öneririm:

svn st | cut -c8- | while read FILE; do echo whatever with "$FILE"; done

% 100 emin olmak ve sonunda beyaz boşluklu süslü dosya adları ile uğraşmak istiyorsanız, xml çıktısını ayrıştırmanız gerekir:

svn st --xml | grep -o 'path=".*"' | sed 's/^path="//; s/"$//'

Elbette grep / sed yerine gerçek bir XML ayrıştırıcı kullanmak isteyebilirsiniz.

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.