Как bash интерпретирует тройные скобки?

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

#read in data
df=read.table("DwoC", header=T)
#transpose it
df <- as.data.frame(t(df))
# remove.1,.2,...strings from row names, and save unique row names
rn=unique(gsub("\\..*","",rownames(df)))
n=3
# calculate means between each 3 rows
dd=aggregate(df,list(rep(1:(nrow(df)%/%n+1),each=n,len=nrow(df))),mean)[-1]
# transpose it back
dt <- as.data.frame(t(dd))
# rename columns as the names were lost during transpose step
names(dt)=rn 
1
13.04.2021, 19:14
1 ответ

Приказ. $(((i=18))), вы правы, это может быть как $(( (i=18) )), так и $( ((i=18)) ), оба варианта допустимы. Несколько распространенный (и, безусловно, простой)способ интерпретации неоднозначных случаев, подобных этому, — это распознавание самого длинного действительного оператора. Это означало бы, что это будет интерпретироваться как $((, за которым следует (.

Вот что происходит, например, с. <<(в Bash и Ksh :это <<, за которым следует (, а не <, за которым следует <(. Несмотря на то, что первая интерпретация является синтаксической ошибкой, вторая верна! Пользователь должен добавить пробел, чтобы оболочка могла это понять. Точно так же i+++aесть i++ + a, а не i + ++a. Подобные вещи существуют и в других языках.

Но с $(((это не совсем так. Некоторые оболочки смотрят дальше, некоторые нет. Рассмотрим, например. это:

echo $((echo hi); (echo ho))

Если интерпретируется как подстановка команды, она действительна и выводит hi ho. Но жадное распознавание $((интерпретировало бы его как арифметическое расширение, и как таковое, это полная подделка.

За исключением Dash и Busybox, все оболочки, которые я пробовал, распознают в них допустимую подстановку команд. Помещение пробела между первыми двумя круглыми скобками делает его однозначным.

As a matter of fact, it looks command substitutions come before arithmetic expansions

Нет, они происходят в одной и той же точке обработки. Чтобы убедиться в этом, создайте подстановку команд, которая расширяется до допустимого арифметического расширения. Например. echo '$((1+2))'печатает $((1+2)); поэтому $( echo '$((1+2))' )расширяется до $((1+2)). Но это не обрабатывается в рамках той же команды.

Это,

echo $( echo '$((1+2))' )

выводит $((1+2)), а не 3.

Конечно, арифметическое разложение может производить только числа, поэтому обратный порядок не может быть проверен. Но подобные эксперименты можно проводить между расширением переменных/параметров и подстановкой команд, и ни в одном из случаев результаты одного расширения не расширяются дальше.


Расширение фигурной скобки , с другой стороны, отличается.

Bash обрабатывает его перед раскрытием переменных:

$ bash -c 'v=000 va=123 vb=456; echo $v{a,b}; n=1 m=4; echo {$n..$m}'
123 456
{1..4}

а Кш делает наоборот:

$ ksh -c 'v=000 va=123 vb=456; echo $v{a,b}; n=1 m=4; echo {$n..$m}'
000a 000b
1 2 3 4

(В Ksh даже a="{1.."; b="4}"; echo $a$bрасширяет фигурную скобку и выводит 1 2 3 4. Zsh снова является разумным здесь, он сначала расширяет переменные, но не позволяет расширенным фигурным скобкам запускать дальнейшее расширение. Zsh также распознает <<(как < <(.)

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

2
28.04.2021, 22:52

Теги

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