Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List comprehension in pure BASH?

Is it possible to do LC like in python and other languages but only using BASH constructs?

What I would like to be able to do, as an example is this:

function ignoreSpecialFiles()
{
    for options in "-L" "-e" "-b" "-c" "-p" "-S" "! -r" "! -w"; do
        if [[ $options "$1" -o $options "$2" ]];then
            return $IGNORED
        fi
    done
}

instead of using code like this:

if [[ -L "$1" -o -e "$1" -o -b "$1" -o -c "$1" -o -p "$1" -o -S "$1" -o\
! -r "$1" -o ! -w "$1" ]]

Do you know of any recipes for simulating LC like this??

Edit:

A more LC specific example:

M = [x for x in S if x % 2 == 0] #is python

what is the most pythonic way to do the same in bash?

for x in S; do if x % 2 == 0;then (HERE MY HEAD EXPLODES) fi done
like image 557
Robert Parcus Avatar asked Jul 16 '11 22:07

Robert Parcus


People also ask

What is list comprehension explain?

List comprehension is an easy to read, compact, and elegant way of creating a list from any existing iterable object. Basically, it's a simpler way to create a new list from the values in a list you already have. It is generally a single line of code enclosed in square brackets.

What languages have list comprehensions?

List comprehensions are used in a variety of languages. They are most often found in functional languages like Haskell and Scala and in scripting languages like Python and Perl. They are typically faster than other methods of building lists, such as for loops.

Are list comprehensions declarative?

List comprehensions are also more declarative than loops, which means they're easier to read and understand. Loops require you to focus on how the list is created. You have to manually create an empty list, loop over the elements, and add each of them to the end of the list.

Why is it called list comprehension?

Because it's a very comprehensive way to describe a sequence (a set in math and other languages, and a list/sequence in Python).


2 Answers

A loop in a command substitution looks like a list comprehension if you squint. Your second example could be written as:

M=$(for x in $S; do if [ $(( x % 2 )) == 0 ]; then echo $x; fi done)
like image 117
slowdog Avatar answered Sep 17 '22 18:09

slowdog


Here's a semi-general format for doing the equivalent of LC in bash with arrays:

outarray=()
for x in "${inarray[@]}"; do
    if SOMECONDITION; then
        outarray+=(SOMEFUNCTIONOFx)
    fi
done

Here's your second example in this format:

s=({1..10})
echo "${s[@]}"
# Prints: 1 2 3 4 5 6 7 8 9 10
m=()
for x in "${s[@]}"; do
    if (( x % 2 == 0 )); then
        m+=($x)
    fi
done
echo "${m[@]}"
# Prints: 2 4 6 8 10

Here's another example, with a less trivial "function" but without the conditional:

paths=("/path/to/file 1" "/path/somewhere/else" "/this/that/the other" "/here/there/everywhere")
filenames=()
for x in "${paths[@]}"; do
    filenames+=( "$(basename "$x")" )
done
printf "'%s' " "${filenames[@]}"
# Prints: 'file 1' 'else' 'the other' 'everywhere' 
like image 31
Gordon Davisson Avatar answered Sep 16 '22 18:09

Gordon Davisson