Her bir giriş borusu için bir komut komutu verin.


162

Her maç için bir java komutu çalıştırmak istiyorum ls | grep pattern -. Bu durumda, yapabileceğimi düşünüyorum find pattern -exec java MyProg '{}' \;ama genel durumu merak ediyorum - "standart girdilerin her satırı için bir kez komut çalıştır" demenin kolay bir yolu var mı? (Balıkta veya levrekte)

Yanıtlar:


91

İşte xargsbu.

... | xargs command

25
Tam değil. printf "foo bar\nbaz bat" | xargs echo wheeüretecek whee foo bar baz bat. Belki -Lveya -nseçeneklerini ekleyin ?
Jander,

3
@Jander Soru oldukça geneldi, bu yüzden genel aracı verdim. Doğru, davranışını belirli koşullara bağlı olarak seçeneklerle ayarlamanız gerekecek.
Keith,

4
... | tr '\ n' '\ 0' | xargs -0
vrdhn

7
"Soruya doğru cevabı veren özel koşullar" gibi. :)
mattdm

7
Bunu xargs ile yapmanın uygun yolunu görmek istiyorsanız, aşağıdaki cevaba bakınız.
Michael Goldshteyn

167

Kabul cevap doğru karar verdi, ancak anahtar geçmektir anlamına anahtarı, "çıktı satır başına bir kere komutu yürütün:"xargs-n1

cat file... | xargs -n1 command

Veya, tek bir giriş dosyası için borunun cattamamen dolmasını önleyebilirsiniz ve sadece:

<file xargs -n1 command

1
Ayrıca ilgi yeteneğidir xargsiçin değil eğer çalıştırmak stdinboş: --no-run-if-empty -r: Standart girdi herhangi nonblanks içermiyorsa, komutunu çalıştırın yoktur. Normalde, komut girilmemiş olsa bile bir kez çalıştırılır. Bu seçenek bir GNU uzantısıdır.
Ronan Jouchet

4
İçerideki çizgiye nasıl ulaşıyorsun command?
BT

Bu, xargs'ın doğru kullanımıdır. -N1 olmadan, yalnızca parametre listelerini, hepsinin yapmadığı çoklu başlatmalar olarak değerlendiren komutlar üzerinde çalışır.
masterxilo

3
printf "foo bar \ nbaz yarasa" | xargs -n1 echo whee sözcüklerle satırlara göre böler
Gismo Ranas

112

Bash veya başka bir Bourne tarzı kabuğunda (kül, ksh, zsh,…):

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

read -rstandart girdiden tek bir satır okur ( readolmadan -r, yorumlanması ters eğik, bunu istemiyorum). 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

6
Ben denedim tail -f syslog | grep -e something -e somethingelse| while read line; do echo $line; doneişe yaramadı. Döngüye borulanmış bir dosyayla whileçalıştı, sadece tail -fçalıştı, sadece çalıştı grep, ancak her iki boruyla da çalıştı . Verilmesi seçeneği o iş yapılmışgrep--line-buffered

Bu, her hattın stdin'e gönderilmesi gerektiğinde de çalışır:command | while read -r line; do echo "$line" | command ; done
Den

21

Keith ile aynı fikirdeyim, xargs iş için en genel araçtır.

Genelde 3 adımlı bir yaklaşım kullanırım.

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

Daha küçük ve daha hızlı yollar var, ama bu yollar neredeyse her zaman işe yarıyor.

Basit bir örnek:

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

ilk 2 satır birlikte çalışacak bazı dosyaları seçer, ardından awk yürütmek için bir komutla güzel bir dize hazırlar ve bazı argümanlar ve $ 1, borudan gelen ilk sütun girişidir. Ve nihayet xargs'ın bu dizgiyi bash'a göndermesini sağlıyorum.

Bu biraz overkill, ancak bu tarif çok esnek olduğu için bana birçok yerde yardımcı oldu.


6
Not, xargs -0boş bayt'ı bir kayıt ayırıcı olarak kullanır, bu nedenle awk print printf("MyJavaProg --args \"%s\"\0",$1)
ifadeniz şöyle

@glenn: Null karakterini kaçırdım, cevabı güncelleyecektir
Johan

@Johan değil büyük bir anlaşma, ancak kullandığınız takdirde awkbunu desen maçı yapmak zorunda ve atlayabilirsiniz grep örneğin,ls | awk '/xls/ {print...
Eric Renouf

15

GNU Parallel bu tür işler için yapılır. En basit kullanım:

cat stuff | grep pattern | parallel java MyProg

Daha fazla bilgi edinmek için tanıtım videosunu izleyin: http://www.youtube.com/watch?v=OpaiGYxkSuQ


1
catBuraya grepdoğrudan ihtiyaç yok çünkü dosyayı doğrudan okuyabiliyor
Eric Renouf


1
Bağlantı için teşekkürler, okumasının daha kolay olduğu konusunda hemfikir değilim, ancak bunun ne olursa olsun kabul edildiğini bilmek güzel. Alternatif şimdi değil < stuff grep patternama grep pattern stuffhiçbir yönlendirme veya kedi gerektirmediğinden , bağlantının burada gerçekten geçerli olmadığını ancak şimdi biraz azarlayabilirim . Yine de, bu tartışmanızı maddi olarak değiştirmez ve her şeyi bir boruda her zaman kullanmanın daha net olduğunu düşünüyorsanız, o zaman catsize güç verin
Eric Renouf

8

Ayrıca, while readbalık kabuğundaki ilmek ( etiketini kullandığınızı balık kabuğu istediğinizi varsayalım ).

command | while read line
    command $line
end

Dikkat edilecek birkaç nokta var.

  • readalmaz -rargüman ve en yaygın kullanım şeklidir kolaylaştırmak amacıyla, sizin ters eğik çizgi yorumlayamaz.
  • $lineBash'tan farklı olarak, balık değişkenleri boşluklarla ayırmadığından alıntı yapmanız gerekmez .
  • commandkendi başına bir sözdizimi hatasıdır (yer tutucu argümanlarının bu tür kullanımını yakalamak için). Gerçek komutla değiştirin.

Does not whileile eşleştirilmiş olması gerekir dove doneyerine end?
aff

@aff Bu özellikle, farklı sözdizimlerine sahip balık kabuğuyla ilgilidir.
Konrad Borowski

Ah, yani işte ne balık anlamına gelir.
aff

6

Girdi argümanının tam olarak komut satırına ekleneceği yeri kontrol etmeniz gerekiyorsa veya birkaç kez tekrarlamanız gerekiyorsa kullanmanız gerekir xargs -I{}.

ÖRNEK 1

another_folderGeçerli dizindeki alt klasörleri yansıtan boş bir klasör yapısı oluşturun :

    ls -1d ./*/ | xargs -I{} mkdir another_folder/{}
ÖRNEK 2

Stdin'den gelen bir dosya listesine bir işlem uygulayın, bu durumda .htmlbir .bakuzantı ekleyerek her dosyanın bir kopyasını alın :

    find . -iname "*.html" | xargs -I{} cp {} {}.bak

Gönderen xargsMacOS / BSD man sayfasına :

 -I replstr
         Execute utility for each input line, replacing one or more occurrences of
         replstr in up to replacements (or 5 if no -R flag is specified) arguments
         to utility with the entire line of input.  The resulting arguments, after
         replacement is done, will not be allowed to grow beyond 255 bytes; this is
         implemented by concatenating as much of the argument containing replstr as
         possible, to the constructed arguments to utility, up to 255 bytes.  The
         255 byte limit does not apply to arguments to utility which do not contain
         replstr, and furthermore, no replacement will be done on utility itself.
         Implies -x.

Linux xargsadam sayfası :

   -I replace-str
          Replace  occurrences of replace-str in the initial-
          arguments with names read from standard input.  Al
          so,  unquoted  blanks do not terminate input items;
          instead the separator  is  the  newline  character.
          Implies -x and -L 1.

1

Potansiyel olarak sterilize edilmemiş girdilerle uğraşırken, işimden önce (özellikle insanların posta kutularını temizlemek gibi yıkıcı bir şey olduğunda) tüm işin görsel denetim için satır satır sıralandığını görmek isterim.

Bu yüzden yaptığım bir parametre listesi (örneğin, kullanıcı adı) oluşturmak, onu bir satır başına kayıt şeklinde bir dosyaya beslemek, bunun gibi:

johndoe  
jamessmith  
janebrown  

Sonra listeyi açtım vimve şu şekilde yürütülmesi gereken tam komutların bir listesini bulana kadar onu ara ve değiştir ifadeleriyle yönetiyorum:

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

Bu şekilde regex'iniz eksikse, hangi komutun potansiyel problemleri olacağını göreceksiniz (örn. /bin/rm -fr johnnyo connor). Bu şekilde regex'inizi geri alabilir ve daha güvenilir bir sürümüyle tekrar deneyebilirsiniz. İsim yönetimi bu konuda çok ünlüydü, çünkü Van Gogh, O'Connors, St. Clair, Smith-Wesson gibi tüm son durumlarla ilgilenmek zor.

Having set hlsearchbu işi için yararlıdır vimtüm maçları vurgulayacaktır gibi, bu yüzden istenmeyen bir şekilde eşleşecek veya maçlar etmezse kolayca tespit edebilirsiniz.

Regex'iniz mükemmel olduğunda ve test edebileceğiniz / düşünebileceğiniz tüm vakaları yakaladığında, genellikle başka bir çalışma için tamamen otomatik hale getirilebilmesi için genellikle sed ifadesine dönüştürürüm.

Giriş satırı sayısının görsel bir inceleme yapmanıza engel olduğu durumlar için, çalıştırmadan önce komutun ekrana (veya daha iyisi bir kayıt) yankılanmasını şiddetle tavsiye ederim, bu nedenle eğer hata çıkarsa, tam olarak hangi komutun neden olduğunu bilirsiniz. başarısız. Ardından, orijinal regex'inize dönebilir ve bir kez daha ayarlayabilirsiniz.


0

Bir program boruyu yok sayar ancak dosyaları argüman olarak kabul ederse, onu özel dosyaya yönlendirebilirsiniz /dev/stdin.

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

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

$ \nBash'ın newline'lere çevrilmesi için gereklidir . Neden olduğundan emin değilim.



0

Burada, hemen kullanabileceğiniz bir kopya macunu:

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

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

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.