Как использовать переменную среды внутри строки в кавычках в Bash

Я пробовал различные формы следующего в сценарии bash:

#!/bin/bash
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Но я не могу получить синтаксис для правильного расширения переменной среды COLUMNS.

Я пробовал различные формы следующего:

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W $COLUMNS'

а также

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W ${COLUMNS}'

а также

eval svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Предложения?


person Jamie    schedule 08.05.2009    source источник
comment
так что эти примеры производят в вашем случае? И что вы хотите, чтобы они производили?   -  person    schedule 08.05.2009
comment
команда вне скрипта работает?   -  person dfa    schedule 08.05.2009
comment
Вы пробовали svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W ""$COLUMNS"   -  person Qian Chen    schedule 30.11.2015
comment
Кстати, использование $@ без кавычек делает его точно таким же, как $*, то есть разбивает "foo bar" на два отдельных аргумента, foo и bar. Если вы хотите сохранить исходный список аргументов в том виде, в каком он был вам предоставлен, вам нужен "$@".   -  person Charles Duffy    schedule 21.09.2017
comment
См. Разницу между одинарными и двойными кавычками в Bash.   -  person codeforester    schedule 21.12.2017


Ответы (5)


Если вы не уверены, вы можете использовать запрос «cols» на терминале и забыть о COLUMNS:

COLS=$(tput cols)
person TheBonsai    schedule 09.05.2009
comment
По какой-то причине это единственное решение, которое мне удалось найти на этой странице (по состоянию на 11 мая, 10:38 по восточному времени). Спасибо - person Jamie; 11.05.2009

Просто краткое примечание/резюме для всех, кто пришел сюда через Google в поисках ответа на общий вопрос, заданный в заголовке (как и я). Любое из следующего должно работать для получения доступа к переменным оболочки внутри кавычек:

echo "$VARIABLE"
echo "${VARIABLE}"

Использование одинарных кавычек является основной проблемой. Согласно справочному руководству Bash:

Заключение символов в одинарные кавычки (') сохраняет буквальное значение каждого символа в кавычках. Одинарная кавычка не может находиться между одинарными кавычками, даже если перед ними стоит обратная косая черта. [...] Заключение символов в двойные кавычки (") сохраняет буквальное значение всех символов в кавычках, за исключением $, `, \ и, когда расширение истории включено, !. Символы $ и ` сохраняют свое особое значение в двойных кавычках (см. Расширения оболочки). Обратная косая черта сохраняет свое особое значение, только если за ней следует один из следующих символов: $, `, ", \ или символ новой строки. В двойных кавычках обратная косая черта, за которой следует один из этих символов, удаляется. Обратная косая черта, предшествующая символам без специального значения, остается неизменной. Двойная кавычка может быть заключена в двойные кавычки, если перед ней поставить обратную косую черту. Если включено, расширение истории будет выполнено, если ! в двойных кавычках не экранировано с помощью обратной косой черты. Обратная косая черта перед ! не удаляется. Специальные параметры * и @ имеют особое значение, если они заключены в двойные кавычки (см. Расширение параметров оболочки).

В конкретном случае, заданном в вопросе, $COLUMNS — это специальная переменная с нестандартными свойствами (см. ответ lhunath выше).

person RecursivelyIronic    schedule 23.02.2012

Обратите внимание, что COLUMNS это:

  1. НЕ переменная среды. Это обычный параметр bash, который устанавливается самим bash.
  2. Устанавливается автоматически при получении сигнала SIGWINCH.

Этот второй пункт обычно означает, что ваша переменная COLUMNS будет установлена ​​только в вашей интерактивной оболочке, не в скрипте bash.

Если stdin вашего скрипта подключен к вашему терминалу, вы можете вручную посмотреть ширину вашего терминала, спросив свой терминал:

tput cols

И чтобы использовать это в вашей команде SVN:

svn diff "$@" --diff-cmd /usr/bin/diff -x "-y -w -p -W $(tput cols)"

(Примечание: вы должны цитировать "$@" и держаться подальше от eval ;-))

person lhunath    schedule 11.05.2009
comment
Спасибо за информацию; знание того, что происходит, приносит чувство катарсиса. - person Jamie; 11.05.2009

Следующий скрипт работает для меня с несколькими значениями $COLUMNS. Интересно, не устанавливаете ли вы COLUMNS перед этим вызовом?

#!/bin/bash
COLUMNS=30
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

Можете ли вы повторить $COLUMNS внутри своего скрипта, чтобы увидеть, правильно ли он установлен?

person Alex B    schedule 08.05.2009
comment
Бу, шипение по поводу $@ без кавычек -- что разбивает один параметр "two words" на два отдельных параметра, two и words. Должно быть "$@", чтобы передать список аргументов точно так, как он был задан. - person Charles Duffy; 21.09.2017

Вы делаете это правильно, поэтому я думаю, что что-то еще не так (не экспорт COLUMNS?).

Уловка для отладки этих случаев состоит в том, чтобы сделать специализированную команду (замыкание для парней с языком программирования). Создайте сценарий оболочки с именем diff-columns, выполняющий:

exec /usr/bin/diff -x -y -w -p -W "$COLUMNS" "$@"

и просто использовать

svn diff "$@" --diff-cmd  diff-columns

Таким образом, ваш код будет чище для чтения и станет более модульным (подход «сверху вниз»), и вы сможете протестировать код столбцов сравнения почти отдельно (подход «снизу вверх»).

person Colas Nahaboo    schedule 09.05.2009
comment
Командная строка анализируется перед разветвлением процесса, поэтому отсутствие экспорта COLUMNS не может быть проблемой. - person Peter van der Heijden; 09.05.2009
comment
Он говорит, что его код является частью сценария bash, поэтому проблема может быть в нем. - person Colas Nahaboo; 09.05.2009