Подтвердить что ты не робот

Цитирование через элементы переменной пути в Bash

Я хочу пропустить список путей, который я получил от команды echo $VARIABLE.

Например:

echo $MANPATH вернет

/usr/lib:/usr/sfw/lib:/usr/info

Итак, это три разных пути, каждый из которых разделен двоеточием. Я хочу зациклиться на каждом из этих путей. Есть ли способ сделать это? Спасибо.

Спасибо за все ответы до сих пор, похоже, что на самом деле мне не нужен цикл. Мне просто нужен способ вывести двоеточие, поэтому я могу запустить одну команду ls на этих трех путях.

4b9b3361

Ответ 1

Вы можете использовать замену шаблона Bash для заполнения переменной цикла. Например:

MANPATH=/usr/lib:/usr/sfw/lib:/usr/info

# Replace colons with spaces to create list.
for path in ${MANPATH//:/ }; do
    echo "$path"
done

Примечание. Не добавляйте расширение подстановки в кавычки. Вы хотите, чтобы расширенные значения из MANPATH интерпретировались for-loop как отдельные слова, а не как одна строка.

Ответ 2

Вы можете установить внутренний разделитель полей:

( IFS=:
  for p in $MANPATH; do
      echo "$p"
  done
)

Я использовал подоболочку, поэтому изменение IFS не отражается в моей текущей оболочке.

Ответ 3

Канонический способ сделать это в Bash состоит в том, чтобы правильно использовать встроенный read:

IFS=: read -r -d '' -a path_array < <(printf '%s:\0' "$MANPATH")

Это единственное надежное решение: сделайте именно то, что вы хотите: разделите строку на разделителе : и будьте безопасны в отношении пробелов, символов новой строки и символов глобуса, таких как *, [ ] и т.д. (в отличие от других ответов: все они сломаны).

После этой команды у вас будет массив path_array, и вы можете установить его на нем:

for p in "${path_array[@]}"; do
    printf '%s\n' "$p"
done

Ответ 4

Таким образом, вы можете спокойно пройти через $PATH с одним циклом, а $IFS останется тем же самым внутри или вне цикла.

while IFS=: read -d: -r path; do # `$IFS` is only set for the `read` command
    echo $path
done <<< "${PATH:+"${PATH}:"}"   # append an extra ':' if `$PATH` is set

Вы можете проверить значение $IFS,

IFS='xxxxxxxx'
while IFS=: read -d: -r path; do
    echo "${IFS}${path}"
done <<< "${PATH:+"${PATH}:"}"

и результат будет примерно таким.

xxxxxxxx/usr/local/bin
xxxxxxxx/usr/bin
xxxxxxxx/bin

Ссылка на еще один вопрос в StackExchange.

Ответ 5

Вы можете использовать Bash для X в нотации ${}, чтобы выполнить следующее:

for p in ${PATH//:/$'\n'} ; do
    echo $p;
done

Ответ 6

IFS=:
arr=(${MANPATH})
for path in "${arr[@]}" ; do # <- quotes required
   echo $path
done

... он заботится о пространствах: o), но также добавляет пустые элементы, если у вас есть что-то вроде:

:/usr/bin::/usr/lib:

... тогда индекс 0,2 будет пустым (''), не могу сказать, почему index 4 не установлен вообще

Ответ 7

for p in $(echo $MANPATH | tr ":" " ") ;do
    echo $p
done