(bash) Каков наименее избыточный способ систематического применения изменений к массиву переменных? - PullRequest
0 голосов
/ 24 апреля 2020

Моя цель - проверить список путей к файлам, если они заканчиваются на "/", и удалить его, если это так.

В идеале я хотел бы изменить исходные переменные FILEPATH, чтобы отразить это изменение, и я хотел бы, чтобы это работало для длинного списка без ненужной избыточности. Я попытался сделать это как al oop, но изменения не изменили исходные переменные, он просто изменил итерационную переменную "EACH_PATH". Кто-нибудь может придумать лучший способ сделать это?

Вот мой код:

FILEPATH1="filepath1/file1"
FILEPATH2="filepath2/file2/"
PATH_ARRAY=(${FILEPATH1} ${FILEPATH2})
echo ${PATH_ARRAY[@]}
for EACH_PATH in ${PATH_ARRAY[@]}
    do
        if [ "${EACH_PATH:$((${#EACH_PATH}-1)):${#EACH_PATH}}"=="/" ]
            then EACH_PATH=${EACH_PATH:0:$((${#EACH_PATH}-1))}
        fi
done

edit: я счастлив сделать это совершенно другим способом и отказаться от кода выше Я просто хочу знать самый элегантный способ сделать это.

Ответы [ 2 ]

0 голосов
/ 26 апреля 2020

Использование sed

PATH_ARRAY=($(echo ${PATH_ARRAY[@]} | sed 's#\/ ##g;s#/$##g'))

Демо:

$FILEPATH1="filepath1/file1"
$FILEPATH2="filepath2/file2/"
$PATH_ARRAY=(${FILEPATH1} ${FILEPATH2})
$echo ${PATH_ARRAY[@]}
filepath1/file1 filepath2/file2/
$PATH_ARRAY=($(echo ${PATH_ARRAY[@]} | sed 's#\/ ##g;s#/$##g'))
$echo ${PATH_ARRAY[@]}
filepath1/file1 filepath2/file2
$
0 голосов
/ 25 апреля 2020

Мне не совсем понятна реальная цель, но в зависимости от ситуации я вижу несколько возможных решений. Лучшее (если это сработает в данной ситуации) - обойтись без отдельных переменных и просто использовать записи массива. Например, вы можете использовать:

declare -a filepath
filepath[1]="filepath1/file1"
filepath[2]="filepath2/file2/"
for index in "${!filepath[@]}"; do
    if [[ "${filepath[index]}" = *?/ ]]; then
        filepath[index]="${filepath[index]%/}"
    fi
done

... и затем использовать "${filepath[x]}" вместо "$FILEPATHx" повсюду. Некоторые примечания:

  • Я использовал строчные имена. Как правило, лучше избегать имен всех заглавных букв, поскольку их много со специальными функциями, и случайное использование одного из этих имен может вызвать проблемы.
  • "${!filepath[@]}" получает список индексов массива (в данном случае «1», «2»), а не их значения; это необходимо, чтобы мы могли устанавливать записи, а не просто просматривать их.
  • Я изменил логи c теста sla sh -trimming - он использует [[ = ]] сделать сопоставление с шаблоном, чтобы увидеть, заканчивается ли запись символом "/" и имеет по крайней мере один символ перед этим (то есть это не просто"/", потому что вы не хотите обрезать который). Затем он использует в расширении %/, чтобы просто обрезать "/" от конца значения.

Если массив с числовым индексированием не будет работать (и у вас есть по крайней мере bash версия 4), как насчет массива с индексированной строкой ("ассоциативный")? Это очень похоже, но используйте declare -A и используйте $ для переменных в индексе (и обычно их заключайте в кавычки). Примерно так:

declare -A filepath
filepath["foo"]="filepath1/file1"
filepath["bar"]="filepath2/file2/"
for index in "${!filepath[@]}"; do
    if [[ "${filepath["$index"]}" = *?/ ]]; then
        filepath["$index"]="${filepath["$index"]%/}"
    fi
done

Если вам действительно нужны отдельные переменные вместо записей массива, вы можете использовать массив переменных names и косвенные ссылки на переменные. как это работает варьируется между различными оболочками и может быть небезопасным в зависимости от того, что находится в ваших данных (в данном случае, в частности, от path_array). Вот способ сделать это в bash:

filepath1="filepath1/file1"
filepath2="filepath2/file2/"
path_array=(filepath1 filepath2)
for varname in "${path_array[@]}"; do
    if [[ "${!varname}" = *?/ ]]; then
        declare "$varname=${!varname%/}"
    fi
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...