Благодаря идеям из комментариев и других источников я, наконец, смог написать этот код и ответить на свой вопрос:
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-й столбцы и удаляет их. Спасибо!
В оболочке 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:]]
будет проверять алфавитные символы в вашей локали , в то время как некоторые оболочки принимают только буквенные символы из переносимого набора символов в своей переменной)