Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

loop with more than one item at a time

We can iterate over a set of items, considering one at a time, like this:

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

How can we process several items at a time in a similar loop? Something like:

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

That second shell script is incorrect but should give an accurate illustration of what I am trying to achieve.

like image 759
Sten Kin Avatar asked Sep 12 '14 18:09

Sten Kin


People also ask

How do you loop multiple values?

To take multiple inputs using a for loop: Declare a new variable and initialize it to an empty list. Use the range() class to loop N times in a for loop. On each iteration, append the user input to the list.

Can you create multiple variables in loop?

How do you put multiple variables in a for loop? And you, too, can now declare multiple variables, in a for-loop, as follows: Just separate the multiple variables in the initialization statement with commas.

Can we run two loops simultaneously?

How do I run two loops at the same time in Arduino? Arduino is not multitasking device, so you cannot run two loops simultaneously. However you can connect 2–3 arduinos using I2C and configure the whole setup to run different loops simultaneously on different arduinos.

Can you have 2 for loops in Python?

Nested For LoopsLoops can be nested in Python, as they can with other programming languages. The program first encounters the outer loop, executing its first iteration. This first iteration triggers the inner, nested loop, which then runs to completion.


4 Answers

Assuming you don't have too many items (although the shell should be able to handle quite a few positional arguments.

# Save the original positional arguments, if you need them
original_pp=( "$@" )
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[@]}"

For POSIX compatibility, use [ "$#" -gt 0 ] instead of the ((...)) expression. There's no easy way to save and restore all the positional parameters in a POSIX-compatible way. (Unless there is a character you can use to concatenate them unambiguously into a single string.)

Here is the subshell jm666 mentions:

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

Any changes to parameters you set inside the subshell will be lost once the subshell exits, but the above code is otherwise POSIX-compatible.

like image 124
chepner Avatar answered Oct 05 '22 04:10

chepner


If filenames does not contain spaces:

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

Edit:

I removed -print0 and -0.

like image 33
Cyrus Avatar answered Oct 05 '22 04:10

Cyrus


Bit late answer, I would do this with non-spectacular way :), like:

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)
like image 39
jm666 Avatar answered Oct 05 '22 03:10

jm666


To get to get n items a time from the list I think you want to get n items from an array.

Use it like this:

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

echo "${arr[@]:0:$n}"
a b c
like image 20
anubhava Avatar answered Oct 05 '22 03:10

anubhava