it-swarm-tr.com

Borulu giriş satırı başına bir komut mu uygulansın?

Ben bir Java ls | grep pattern - Her maç için bir kez komut çalıştırmak istiyorum.Bu durumda, ben find pattern -exec Java MyProg '{}' \; Yapabileceğini düşünüyorum ama merak ediyorum genel durum - "her standart girdi satırı için bir kez komut çalıştır" demenin kolay bir yolu var mı?

176
Xodarap

xargs bunu yapar.

... | xargs command
98
Keith

Kabul edilen cevap doğru fikre sahip, ancak anahtar xargs the -n1 anahtarı, yani "Çıktı satırı başına komutu bir kez çalıştır:"

cat file... | xargs -n1 command

Ya da, tek bir giriş dosyası için, borunun cat 'den tamamen kaçınmasını ve aşağıdakilerle devam etmesini sağlayabilirsiniz:

<file xargs -n1 command
193

Bash veya Bourne tarzı herhangi bir Kabukta (kül, ksh, zsh,…):

while read -r line; do command "$line"; done

read -r standart girişten tek bir satır okur (read olmadan -r ters eğik çizgileri yorumlar, bunu istemezsiniz). Böylece aşağıdakilerden birini yapabilirsiniz:

$ command | while read -r line; do command "$line"; done  

$ while read -r line; do command "$line"; done <file
117
Steven D

Keith'e katılıyorum, xargs bu iş için en genel araçtır.

Genellikle 3 aşamalı bir yaklaşım kullanıyorum.

  • çalışmak istediğiniz bir şey olana kadar temel şeyleri yapın
  • doğru sözdizimini elde etmek için satırı awk ile hazırlayın
  • o zaman xargs'ın onu çalıştırmasına izin verin, belki bash yardımıyla.

Daha küçük ve daha hızlı yollar vardır, ancak bu yollar neredeyse her zaman çalışır.

Basit bir örnek:

ls | 
grep xls | 
awk '{print "MyJavaProg --arg1 42 --arg2 "$1"\0"}' | 
xargs -0 bash -c

ilk 2 satır çalışılacak bazı dosyaları seçer, ardından awk yürütme komutuyla bir Nice dizesi ve bazı argümanlar hazırlar ve $ 1 borudan ilk sütun girdisidir. Ve nihayet xargs sadece bu yürütmek bash için bu dize gönderdiğinden emin olun.

Biraz abartılı, ama bu tarif çok esnek olduğu için birçok yerde bana yardımcı oldu.

22
Johan

GNU Parallel bu tür görevler için yapılır. En basit kullanım:

cat stuff | grep pattern | parallel Java MyProg

Daha fazla bilgi edinmek için giriş videosunu izleyin: http://www.youtube.com/watch?v=OpaiGYxkSuQ

15
Ole Tange

Ayrıca, while read Balık kabuğunda döngü (Balık Kabuğu istediğinizi varsayalım, kullandığınız düşünülürse balık etiketi).

command | while read line
    command $line
end

Dikkat edilmesi gereken birkaç nokta.

  • read almıyor -r argümanıdır ve en yaygın kullanım durumunu kolaylaştırmak için ters eğik çizgilerinizi yorumlamaz.
  • Teklif vermenize gerek yok $line, bash'ın aksine, balık değişkenleri boşluklara ayırmaz.
  • command tek başına bir sözdizimi hatasıdır (yer tutucu argümanlarının bu şekilde kullanımını yakalamak için). Gerçek komutla değiştirin.
10
Konrad Borowski

Potansiyel olarak onaylanmamış girdilerle uğraşırken, tüm işi çalıştırmadan önce görsel inceleme için satır satır 'yazıldığını' görmeyi seviyorum (özellikle insanların posta kutularını temizlemek gibi yıkıcı bir şey olduğunda).

Yani ne yaptığım bir parametre listesi (yani. Kullanıcı adları) oluşturmak, satır başına bir kayıt şeklinde bir dosyaya, şöyle beslemek:

johndoe  
jamessmith  
janebrown  

Daha sonra listeyi vim içinde açıyorum ve çalıştırılması gereken tam komutların bir listesini bulana kadar arama ve değiştirme ifadeleriyle değiştiriyorum:

/bin/rm -fr /home/johndoe  
/bin/rm -fr /home/jamessmith 

Bu şekilde normal ifadeniz eksikse, hangi komutta olası sorunların olacağını göreceksiniz (ör. /bin/rm -fr johnnyo connor). Bu şekilde normal ifadenizi geri alabilir ve daha güvenilir bir sürümüyle tekrar deneyebilirsiniz. İsim mangling bununla meşhurdur, çünkü Van Gogh, O'Connors, St. Clair, Smith-Wesson gibi tüm Edge davalarına bakmak zordur.

set hlsearch, tüm eşleşmeleri vurgulayacağı için vim biçiminde bunu yapmak için kullanışlıdır, böylece eşleşmediği veya istenmeyen bir şekilde eşleştiğini kolayca tespit edebilirsiniz.

Normal ifadeniz mükemmel olduğunda ve test edebileceğiniz/düşünebileceğiniz tüm durumları yakaladıktan sonra, genellikle bir sed ifadesine dönüştürürüm, böylece başka bir çalışma için tamamen otomatik hale getirilebilir.

Giriş satırlarının sayısının görsel bir inceleme yapmanızı engellediği durumlarda, komutu çalıştırmadan önce ekrana (veya daha iyisi bir günlüğe) yankılanmanızı öneririm, bu yüzden hata verirse, hangi komutun neden olduğunu tam olarak bilirsiniz. başarısız olur. Ardından orijinal regex'inize geri dönebilir ve bir kez daha ayarlayabilirsiniz.

1
Marcin

Burada, hemen kullanabileceğiniz bir kopya macunu:

cat list.txt | xargs -I{} command parameter {} parameter

Listedeki öğe {} olduğu yere yerleştirilecek ve komutun ve parametrelerin geri kalanı olduğu gibi kullanılacaktır.

1
DustWolf

Bu, diğer cevapların belirttiği gibi xargs ile mümkündür. Sorunun "her satıra bir kez" bölümündeki iki özelliği ayırmamız gerekir:

  1. Bir kez: -n 1, bu komutun her bağımsız değişken için tam olarak bir kez çağrılmasını sağlar. Ancak, varsayılan olarak, xargs, bağımsız değişkenlerin boşlukla sınırlandırıldığını varsayar - dosyalar boşluk içerdiğinde bu kesilir.
  2. Satır başına: -d '\n' veya girişi tr '\n' '\0' ve kullan -0. Bu komutun girişteki boşluklara karşı sağlam olmasını sağlar.

Son komut satırı daha sonra:

.... | xargs -n 1 -d '\n' <command>

veya (tr ile)

.... | tr '\n' '\0' | xargs -n 1 -0 <command>

Komutunuz aynı anda birden fazla bağımsız değişkeni işleyebiliyorsa (grep veya sed gibi), -n 1 birçok durumda işlemi hızlandırmak için.

0
krlmlr

Bir program yöneltmeyi yok sayar, ancak dosyaları bağımsız değişken olarak kabul ederse, yalnızca /dev/stdin.

Java'ya aşina değilim, ama bash için nasıl yapacağınıza dair bir örnek:

$ echo $'pwd \n cd / \n pwd' |bash /dev/stdin
/home/rolf
/

$ Bash'ın \n. Neden olduğundan emin değilim.

0
Rolf

Bunu tercih ederim - çok satırlı komutlara ve açık kodlara izin verme

find -type f -name filenam-pattern* | while read -r F
do
  echo $F
  cat $F | grep 'some text'
done

ref https://stackoverflow.com/a/3891678/248616

0
Nam G VU