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

Могут ли выражения расширения параметра ${var} вставляться в bash?

Что у меня есть:

progname=${0%.*}
progname=${progname##*/}

Может ли это быть вложенным (или нет) в одну строку, т.е. одно выражение?

Я пытаюсь удалить путь и расширение из имени script, чтобы осталось только базовое имя. Вышеуказанные две строки работают нормально. Моя природа "С" просто заставляет меня запутывать их еще больше.

4b9b3361

Ответ 1

Если по гнезду вы имеете в виду что-то вроде этого:

#!/bin/bash

export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

echo ${${HELLO}WORLD}

Тогда нет, вы не можете вложить выражения ${var}. Расширитель синтаксиса bash не сможет его понять.

Однако, если я правильно понимаю вашу проблему, вы можете посмотреть на команду basename - она ​​удаляет путь из заданного имени файла, а если дано расширение, это также разделит. Например, запуск basename /some/path/to/script.sh .sh вернет script.

Ответ 2

Bash поддерживает косвенное расширение:

$ FOO_BAR="foobar"
$ foo=FOO
$ foobar=${foo}_BAR
$ echo ${foobar}
FOO_BAR
$ echo ${!foobar}
foobar

Это должно поддерживать вложенность, которую вы ищете.

Ответ 3

Старый поток, но, возможно, ответ заключается в использовании Indirection: ${! PARAMETER}

Например, рассмотрим следующие строки:

H="abc"
PARAM="H"
echo ${!PARAM} #gives abc

Ответ 4

Следующая опция сработала для меня:

NAME="par1-par2-par3"
echo $(TMP=${NAME%-*};echo ${TMP##*-})

Выход:

par2

Ответ 5

Это вложение не представляется возможным в bash, но оно работает в zsh:

progname=${${0%.*}##*/}

Ответ 6

На самом деле можно создать вложенные переменные в bash, используя два шага.

Вот тест script, основанный на записи Тима, используя идею, предложенную пользователем1956358.

#!/bin/bash
export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

# This command does not work properly in bash
echo ${${HELLO}WORLD}

# However, a two-step process does work
export TEMP=${HELLO}WORLD
echo ${!TEMP}

Вывод:

Hello, world!

Есть много опрятных трюков, объясняемых при запуске ' info bash' из командной строки, затем поиск " Расширение параметров оболочки". Сегодня я читал несколько, просто потерял около 20 минут своего времени, но мои скрипты будут намного лучше...

Обновление: после более подробной информации я предлагаю эту альтернативу по вашему первоначальному вопросу.

progname=${0##*/}

Он возвращает

bash

Ответ 7

Выражения типа ${${a}} не работают. Чтобы обойти это, вы можете использовать eval:

b=value
a=b
eval aval=\$$a
echo $aval

Выход

value

Ответ 8

Я знаю, что это древняя нить, но вот мои 2 цента.

Здесь функция (по общему признанию kludgy) bash, которая позволяет использовать требуемые функции:

read_var() {
  set | grep ^$1\\b | sed s/^$1=//
}

Здесь короткий тест script:

#!/bin/bash

read_var() {
  set | grep ^$1\\b | sed s/^$1=//
}

FOO=12
BAR=34

ABC_VAR=FOO
DEF_VAR=BAR

for a in ABC DEF; do
  echo $a = $(read_var $(read_var ${a}_VAR))
done

Выход, как и ожидалось:

ABC = 12
DEF = 34

Ответ 9

Базеальное имя bultin могло бы помочь в этом, так как вы специально разбиваете на/в одной части:

[email protected]# var=/path/to/file.extension
[email protected]# basename ${var%%.*}
file
[email protected]#

Это не намного быстрее, чем вариант с двумя линиями, но это только одна строка, использующая встроенные функции. Или, используйте zsh/ksh, который может делать объекты, вложенные в шаблон.:)

Ответ 10

Существует 1 строка решения исходного вопроса OP, базовое имя сценария с расширением файла:

progname=$(tmp=${0%.*} ; echo ${tmp##*/})

Здесь другое, но, используя чит для базового имени:

progname=$(basename ${0%.*})

Другие ответы отошли от исходного вопроса OP и сосредоточились на том, возможно ли просто расширить результат выражений с помощью ${!var} но столкнулись с ограничением, что var должен явно совпадать с именем переменной. Сказав это, ничто не помешает вам получить 1-строчный ответ, если вы объедините выражения вместе с точкой с запятой.

ANIMAL=CAT
BABYCAT=KITTEN
tmp=BABY${ANIMAL} ; ANSWER=${!tmp} # ANSWER=KITTEN

Если вы хотите, чтобы это выглядело как отдельный оператор, вы можете вложить его в подоболочку, т.е.

ANSWER=$( tmp=BABY${ANIMAL) ; echo ${!tmp} ) # ANSWER=KITTEN

Интересное использование - косвенные работы над аргументами функции bash. Затем вы можете вкладывать вызовы вашей функции bash для достижения многоуровневой вложенной косвенности, потому что нам разрешено делать вложенные команды:

Вот демонстрация косвенности выражения:

deref() { echo ${!1} ; }
ANIMAL=CAT
BABYCAT=KITTEN
deref BABY${ANIMAL} # Outputs: KITTEN

Вот демонстрация многоуровневой косвенности через вложенные команды:

deref() { echo ${!1} ; }
export AA=BB
export BB=CC
export CC=Hiya
deref AA # Outputs: BB
deref $(deref AA) # Outputs: CC
deref $(deref $(deref AA)) # Outputs: Hiya

Ответ 11

Если мотивация состоит в том, чтобы "обфускать" (я бы сказал, упростил) обработку массива в духе "понимания" Python, создайте вспомогательную функцию, которая выполняет последовательности операций.

function fixupnames()
   {
   pre=$1 ; suf=$2 ; shift ; shift ; args=([email protected])
   args=(${args[@]/#/${pre}-})
   args=(${args[@]/%/-${suf}})
   echo ${args[@]}
   }

Вы можете использовать результат с хорошим однострочным.

$ echo $(fixupnames a b abc def ghi)
a-abc-b a-def-b a-ghi-b

Ответ 12

Хотя это очень старая тема, это устройство идеально подходит для прямого или случайного выбора файла/каталога для обработки (воспроизведения мелодий, выбора фильма для просмотра или книги для чтения и т.д.).

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

e=($(find . -maxdepth 1 -type d))
c=${2:-${e[$((RANDOM%${#e[@]}))]}}

Объяснение: e - это массив имен каталогов, c выбранный каталог, либо явно названный как $ 2,

${2:-...}  

где... альтернативный случайный выбор, заданный

${e[$((RANDOM%${#e[@]}))]}  

где

$((RANDOM%...))  

число, сгенерированное bash, делится на количество элементов в массиве e, определяемое как

${#e[@]}  

получая остаток (от оператора%), который становится индексом для массива e

${e[...]}

Таким образом, у вас есть четыре вложенных расширения.

Ответ 13

Это сработает, если вы будете следовать приведенному ниже способу выполнения промежуточного шага:

export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

varname=${HELLO}WORLD
echo ${!varname}

Ответ 14

eval позволит вам делать то, что вы хотите:

export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

eval echo "\${${HELLO}WORLD}"

Выход: Hello, world