Как перебирать разные списки по параметру - PullRequest
0 голосов
/ 12 февраля 2020

У меня есть скрипт, который может получить список папок или получить их автоматически с помощью find. Я хотел бы написать один l oop, который обрабатывает оба случая: если есть параметры, используйте их, иначе создайте список автоматически.

Пока у меня есть что-то вроде:

if [ "$#" -gt 0 ]
then
    for value in "$@"
    do
        v1=$(process_data "$value")
        <do things with $v1>
    done
else
    for value in "$(find ...)"
    do
        v1=$(process_data "$value")
        <do things with $v1>
    done
fi

Я хотел бы сделать что-то вроде:

if [ "$#" -gt 0 ]
then
    data="$@"
else
    data="$(find ...)"
fi

for value in "${data[@]}"
do
    v1=$(process_data "$value")
    <do things with $v1>
done

, но это data назначение может быть потенциально большим. На языке с указателями это не должно быть проблемой, но в bash это выглядит не очень хорошо.

Есть ли лучший способ удовлетворить мои потребности?

Ответы [ 2 ]

2 голосов
/ 12 февраля 2020

Они выглядят неправильно:

data="$@"
data="$(find ...)"

Если вы хотите, чтобы data был массивом, вам нужно

data=("$@")
data=($(find ...))

Что вы можете сделать, это назначить позиционные параметры:

#!/bin/bash

if [ "$#" = 0 ]
then
    # no arguments; default to all matching files
    set -- $(find ...)
fi

for value in "$@"
do
    # things
done

Это означает, что l oop не может запуститься, пока не завершится команда find. Чтобы решить эту проблему, альтернативой может быть перевернуть его и сделать использование "$@" более похожим на вывод find, то есть направить его в канал, например:

#!/bin/bash

args_or_find() {
    if [ "$#" -gt 0 ]
    then
        printf '%s\n' "$@"
    else
        find ...
    fi
}

while read -r value
do
    # things
done < <(args_or_find)

Естественное расширение улучшить устойчивость, используя \0 вместо \n, так как разделитель оставлен в качестве упражнения.

1 голос
/ 12 февраля 2020

Вы можете использовать такой скрипт для обработки l oop только один раз:

if (($#)); then           # arguments are passed
    arr=("$@")
else                      # build array from find command's result
    arr=()
    while IFS= read -rd '' f; do
        arr+=("$f")
    done < <(find . -name '*.txt' -print0)
fi

# main processing loop
for line in "${arr[@]}"; do
    echo "processing... <$line>"
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...