Что означает подстановка $ {! Var_name + x}?

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

   inputStream | awk -F'\t' -v OFS="\t" '{
            if ( col1 == ""){
                for (i=1;i<=NF;i++){
                    if ($i == "BlueId"){
                        col1=i;
                    }
                    else if ($i == "WhiteId"){
                        col2=i;
                    }
                }
            print "-1" "\t" "-1" "\t" $0
            }
            else {
                print $col1 "\t" $col2 "\t" $0
            }
        }' | sort -k1,1n -k2,2n | cut -f3- | outputStream

Он работает следующим образом: он берет данные потока, находит номера нужных столбцов и печатает перед каждым row оба значения, необходимые для сортировки. Затем он сортирует 1-й и 2-й столбцы и удаляет их. Спасибо!

10
18.02.2019, 16:27
1 ответ

В оболочке bash${!var}— косвенная переменная. Он расширяется до значения переменной, имя которой хранится в $var.

Расширение переменной ${var+value}— это расширение POSIX , которое расширяется до value, если переменная varустановлена ​​(независимо от того, является ли ее значение пустым или нет ).

Комбинируя их, ${!var+x}расширится до x, если установлена ​​переменная, имя которой хранится в $var.

Пример:

$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"

(пустая строка в качестве вывода)


Функция в вопросе может быть сокращена до

check_if_variable_is_set () { [ -n "${!1+x}" ]; }

или даже:

check_if_variable_is_set () { [ -v "$1" ]; }

или даже:

check_if_variable_is_set()[[ -v $1 ]]

Где -v— это проверка bashимени переменной, которая будет истинной, если именованная переменная установлена, и ложной в противном случае.


POSIXly можно было написать:

check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }

Обратите внимание, что все это является потенциальными уязвимостями внедрения команд, если аргумент этой функции может оказаться под контролем злоумышленника. Попробуйте, например, с check_if_variable_is_set 'a[$(id>&2)]'.

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

check_if_variable_is_set() {
  case $1 in
    ("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
    (*)  eval '[ -n "${'"$1"'+x}" ]'
  esac
}

(обратите внимание, что [[:alpha:]]будет проверять алфавитные символы в вашей локали , в то время как некоторые оболочки принимают только буквенные символы из переносимого набора символов в своей переменной)

17
27.01.2020, 20:00

Теги

Похожие вопросы