Як використовувати змінну середовища всередині рядка, що цитується, у Bash


91

Я випробував різні форми наступного у сценарії 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"

Пропозиції?


так що ці приклади дають у вашому випадку? І що ви хочете, щоб вони виробляли?

команда поза сценарієм працює?
dfa

Ви пробувалиsvn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W ""$COLUMNS"
Цянь Чень,

До речі, використання $@uncooted робить це точно так само, як $*- це означає, що воно розпадається "foo bar"на два окремі аргументи, fooі bar. Якщо ви хочете зберегти оригінальний список аргументів так, як він вам був наданий, ви хочете "$@".
Чарльз Даффі,

Відповіді:


16

Якщо ви не впевнені, ви можете використовувати запит "cols" на терміналі і забути СТОЛБЦІ:

COLS=$(tput cols)

З будь-якої причини, це єдине рішення, яке мені вдалося заробити на цій сторінці (станом на 11 / травня 10:38 за європейським часом). Дякую
Джеймі

397

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

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

Основне питання - використання одинарних лапок. Відповідно до довідкового посібника Bash :

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

У конкретному випадку, заданому у питанні, $ COLUMNS - це спеціальна змінна, яка має нестандартні властивості (див. Відповідь lhunath вище).


20
У разі одинарні лапки, може бути , це тимчасове рішення допомагає: 'before'"$variable"'after'(як зазначено в цій відповіді: stackoverflow.com/a/13802438/2254346 )
Makish

Чудова відповідь! У мене була та сама проблема посилання на мою змінну env в одинарних лапках. Після того, як я змінив мою одинарну лапку на подвійну, моя змінна env була розширена, як очікувалося.
Бініта Бхараті,

14

Зверніть увагу, що 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;-))


Спасибі за інформацію; Знання того, що відбувається, призводить до відчуття катарсису.
Джеймі,

2

Наступний сценарій працює для мене для кількох значень $COLUMNS. Цікаво, чи не налаштовуєте ви COLUMNSдо цього дзвінка?

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

Чи можете ви пролунати $COLUMNSвсередині вашого сценарію, щоб перевірити, чи правильно він встановлений?


Бу, шипить re: unquoted $@- це розділяє один параметр "two words"на два окремі параметри, twoі words. Має бути "$@"передавати список аргументів точно так, як він був заданий.
Чарльз Даффі,

0

Ви робите це правильно, тому, мабуть, щось інше винне (не експортуючи СТОЛБЦИ?).

Фокус для налагодження цих випадків полягає у створенні спеціалізованої команди (закриття для хлопців мови програмування). Створіть сценарій оболонки з назвою diff-columns, виконуючи:

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

і просто використовувати

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

Таким чином, ваш код стає чистішим для читання та більш модульним (підхід зверху вниз), і ви можете протестувати код розбіжних стовпців повністю окремо (підхід знизу вгору).


Командний рядок аналізується перед тим, як процес розгалужується, тому проблема експорту СТОЛІЦЬ не може бути.
Пітер ван дер Хейден

1
Він каже, що його код є частиною скрипта bash, отже, це може бути проблемою.
Колас Нахабу,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.