2014-09-12 22 views
11

हम आइटम का एक समूह से अधिक पुनरावृति कर सकते हैं, एक समय में एक विचार, इस तरह:पाश

#!/bin/bash 
for i in $(ls); do 
    echo item: $i 
done 

हम एक ऐसी ही पाश में एक समय में कई मदों कैसे संसाधित कर सकते हैं ? कुछ ऐसा:

#!/bin/bash 
for i,j,k in $(ls); do 
    echo item i: $i 
    echo item j: $j 
    echo item k: $k 
done 

वह दूसरी खोल स्क्रिप्ट गलत है लेकिन मुझे जो हासिल करने की कोशिश कर रहा है उसका सटीक उदाहरण देना चाहिए।

+3

'का उपयोग न करें इस तरह ls': में मैं के लिए उपयोग' *; इसके बजाय करो। – chepner

उत्तर

1

to get n items a time from the list प्राप्त करने के लिए मुझे लगता है कि आप एक सरणी से n आइटम प्राप्त करना चाहते हैं।

इस तरह यह प्रयोग करें: फ़ाइल नाम स्थान न हो

n=3 
arr=(a b c d e) 

echo "${arr[@]:0:$n}" 
a b c 
3

हैं:

find . -maxdepth 1 | xargs -L 3 | while read i j k; do 
    echo item i: $i 
    echo item j: $j 
    echo item k: $k 
done 

संपादित करें:

मैं -print0 और -0 हटा दिया।

+0

असल में, * बिल्कुल * सुरक्षित होने के लिए, आपको '-print0' की आवश्यकता है, साथ ही * 3 * ठीक से निर्मित कॉल 'पढ़ने' की आवश्यकता है। – chepner

+1

मुझे लगता है कि '-print0' और' -0' विकल्प व्हाइटस्पेस वाले फ़ाइल नामों में सहायता कर सकते हैं। – SzG

+1

@ एसजीजी लेकिन केवल जब पढ़ा जाता है तो उन्हें नल समाप्त कर दिया जाता है। अन्यथा, यह व्यर्थ है। और आप 'xargs' का उपयोग करते समय निरंतर समाप्त नहीं किया जा सकता है ... इसलिए, '-print0' और उचित' read' या '-print | xargs' ... दोनों नहीं। – jm666

4

मान लिया जाये कि आप भी कई मदों की जरूरत नहीं है (हालांकि खोल संभाल करने में सक्षम होना चाहिए काफी कुछ स्थितीय तर्क।

# Save the original positional arguments, if you need them 
original_pp=("[email protected]") 
set -- * 
while (($# > 0)); do 
    i=$1 j=$2 k=$3  # Optional; you can use $1, $2, $3 directly 
    ... 
    shift 3 || shift $# # In case there are fewer than 3 arguments left 
done 

# Restore positional arguments, if necessary/desired 
set -- "${original_pp[@]}" 

POSIX संगतता के लिए, ((...)) अभिव्यक्ति के बजाय [ "$#" -gt 0 ] का उपयोग करें। POSIX- संगत तरीके से सभी पोजीशनल पैरामीटर को सहेजने और पुनर्स्थापित करने का कोई आसान तरीका नहीं है। (जब तक कोई ऐसा चरित्र नहीं है जिसे आप एक स्ट्रिंग में अनजाने में संयोजित करने के लिए उपयोग कर सकते हैं।)

यहां सबहेल जेएम है 666 का उल्लेख है:

(
    set -- * 
    while [ "$#" -gt 0 ]; do 
     i=$1 j=$2 k=$3 
     ... 
     shift 3 || shift $# 
    done 
) 

आप subshell अंदर मानदंड सेट करने में कोई भी परिवर्तन एक बार subshell रास्ते खो जाएगा, लेकिन इसके बाद के संस्करण कोड अन्यथा POSIX-संगत है।

+2

आप एक सबहेल का उपयोग कर सकते हैं, जब तक आपको बाद में किसी भी पैरामीटर को सेट करने की आवश्यकता नहीं है। – chepner

-1

आप xargs, awk, sed या paste का उपयोग अपने इनपुट पुनर्गठन कर सकते हैं।

job_select() 
{ 
    ls 
} 

job_process() 
{ 
    while read i j k; do 
    printf 'item i: %s\nitem j: %s\nitem k: %s\n' "$i" "$j" "$k" 
    done 
} 

job_restructure_xargs() 
{ 
    xargs -L 3 
} 

job_rstructure_awk() 
{ 
    awk '(NR % 3 == 1) { i = $0 } (NR % 3 == 2) { j = $0 } (NR % 3 == 0){ k = $0; print(i,j,k)}' 
} 

job_restructure_sed() 
{ 
    sed -e 'N;N;s/\n/ /g' 
} 

job_restructure_paste() 
{ 
    paste - - - 
} 
फिर

संयोजन

job_select | job_restructure_xargs | job_process 
job_select | job_restructure_awk | job_process 
job_select | job_restructure_sed | job_process 
job_select | job_restructure_paste | job_process 

के किसी भी आप क्या चाहते हैं नहीं करता है।

+1

'एलएस' के आउटपुट को पार्स न करें, खासकर ऐसे रूबे-गोल्डबर्ग-एस्क्यू फ्रेमवर्क में नहीं। यह व्हाइटस्पेस युक्त फ़ाइल नामों के लिए काम नहीं करेगा। – chepner

+0

मैंने अभी माना है कि यह 'एलएस' आउटपुट को पार्स करने के लिए सुरक्षित था क्योंकि ओपी ने इसे माना था। शैल प्रोग्रामिंग में, डेटा प्रोसेसिंग फ़िल्टर द्वारा किया जाता है, इसलिए यहां रूब-गोल्डबर्ग जैसे कुछ भी नहीं है, केवल नियमित खोल प्रोग्रामिंग। उस ने कहा, आपका जवाब बहुत बेहतर है! –

+0

मैं रुबे गोल्डबर्ग टिप्पणी वापस लेता हूं; मैंने काफी बारीकी से नहीं देखा, और आपके तीन 'job_restructure_ *' फ़ंक्शन एक ही कार्य के केवल 3 वैकल्पिक कार्यान्वयन नहीं थे। हालांकि, जहां भी यह फसल हो, वहां 'एलएस' को पार्स करने के आग्रह को स्क्वैश करना सबसे अच्छा है। – chepner

1

थोड़ी देर हो चुकी जवाब, मैं गैर शानदार तरीका :) के साथ ऐसा होता है जैसे,:

while read -r -d $'\0' f1 
do 
     read -r -d $'\0' f2 
     read -r -d $'\0' f3 

     echo "==$f1==$f2==$f3==" 

done < <(find test/ ... findargs... -print0) 
0

यहाँ एक ठेठ प्रोग्रामिंग ढंग से एक और उपाय है ->

#!/bin/bash 
shopt -s nullglob 
arr=(*) #read the files/dirs in an array 
total=${#arr[@]} #get the array size 
count=0; 
#loop it thru in multiples of three 
while [ $count -lt $((total-2)) ] 
do 
     echo "i is ${arr[$count]}" 
     echo "j is ${arr[$((count+1))]}" 
     echo "k is ${arr[$((count+2))]}" 
     count=$((count+3)) 
done 
#print the remaining element(s) 
rem=$((total%3));  
if [ $rem -eq 1 ]; 
then 
     echo "i is ${arr[$total-1]}" 
elif [ $rem -eq 2 ]; 
then 
     echo "i is ${arr[$total-2]}" 
     echo "j is ${arr[$total-1]}" 
fi 
echo "Done" 
0

आप तो जीएनयू समानांतर है आप चला सकते हैं:

ls | parallel -N3 "echo item i: {1}; echo item j: {2}; echo item k: {3}" 

सभी नए कंप्यूटर कई कोर है, लेकिन ज्यादातर कार्यक्रमों n में धारावाहिक हैं अचर और इसलिए एकाधिक कोर का उपयोग नहीं करेंगे। हालांकि, कई कार्यों को अत्यंत parallelizeable हैं:

  • एक ही कार्यक्रम चलाने के लिए कई फाइलों पर
  • भागो एक फ़ाइल
  • भागो एक फ़ाइल में हर ब्लॉक के लिए एक ही कार्यक्रम में हर पंक्ति के लिए एक ही कार्यक्रम

जीएनयू समानांतर एक सामान्य समांतरता है और उसी मशीन पर समानांतर में या कई मशीनों पर नौकरियां चलाने में आसान बनाता है जिनके पास आपके पास एसएसएच पहुंच है।

Simple scheduling

जीएनयू समानांतर बजाय एक नई प्रक्रिया जब spawns:

आप 32 विभिन्न नौकरियों आप 4 सीपीयू पर चलाना चाहते हैं, तो parallelize करने के लिए एक सीधे आगे रास्ता प्रत्येक CPU पर 8 नौकरियों को चलाने के लिए है एक खत्म - सीपीयू सक्रिय रखने और समय इस प्रकार की बचत:

GNU Parallel scheduling

स्थापना

एक व्यक्तिगत स्थापना के लिए रूट पहुंच की आवश्यकता नहीं है। यह 10 सेकंड में ऐसा करके किया जा सकता है:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash 

के लिए अन्य स्थापना विकल्पों को देखने के http://git.savannah.gnu.org/cgit/parallel.git/tree/README

जानें

अधिक उदाहरण देखें: http://www.gnu.org/software/parallel/man.html

घड़ी परिचय वीडियो: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

टी के माध्यम से चलना वह ट्यूटोरियल: http://www.gnu.org/software/parallel/parallel_tutorial.html

साइन अप करें ईमेल सूची के लिए प्राप्त करने के लिए समर्थन: https://lists.gnu.org/mailman/listinfo/parallel

+0

मुझे नहीं लगता कि इंटरनेट से यादृच्छिक कोड चल रहा है (यहां तक ​​कि यदि यह सादा http पर है, https नहीं है) तो एक अच्छी सलाह है। (और हाँ, मैं इस "इंस्टॉलर" के बारे में बात कर रहा हूं, स्थापित सॉफ्टवेयर नहीं।) –

+0

यह सामान्य अच्छी सलाह है: डिजिटल हस्ताक्षर (जैसे एपीटी) के माध्यम से सुरक्षित पथ के माध्यम से स्थापित करना बेहतर है। लेकिन कुछ लोगों के पास उस विलासिता नहीं है: हो सकता है कि उनके पास रूट पहुंच न हो, शायद वे एक वितरण का उपयोग करें जिसके लिए जीएनयू समानांतर पैक नहीं किया गया है। इन लोगों के लिए यह सुरक्षा में कोई फर्क नहीं पड़ेगा कि वे इंस्टॉलर को सीधे इंटरनेट से चलाते हैं या वे इंस्टॉल प्रोग्राम चलाते हैं: इनमें से किसी एक में बैकडोर हो सकता है। –

+0

कम से कम इंस्टॉलर के लिए एक https यूआरएल प्रदान करें, इसलिए यदि वे (सही तरीके से) आपकी साइट (और इसके प्रमाण पत्र) पर भरोसा करते हैं, तो उन्हें एक ऐसा संस्करण नहीं मिलेगा जिसे मिटएम हमलावर द्वारा प्रतिस्थापित किया गया हो। –