Bash에서 인용 된 문자열 내에서 환경 변수를 사용하는 방법


94

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"
Qian Chen

BTW, 사용 $@하는 인용되지 않은 차종이 정확히 동일 $*- 그것은 파괴라고하는 "foo bar"두 개의 별도의 인수로, foobar. 원래 인수 목록을 제공된 그대로 보존하려면 "$@".
Charles Duffy

답변:


16

확실하지 않은 경우 터미널에서 'cols'요청을 사용하고 COLUMNS를 잊어 버릴 수 있습니다.

COLS=$(tput cols)

어떤 이유로 든이 페이지에서 작업 할 수있는 유일한 솔루션입니다 (11/5 월 10:38 ET 기준). 감사합니다
Jamie

406

제목에서 묻는 일반적인 질문에 대한 답변을 찾고있는 Google을 통해 여기에 온 모든 사람들을위한 간단한 메모 / 요약입니다. 따옴표 안의 쉘 변수에 액세스하려면 다음 중 하나가 작동해야합니다.

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

작은 따옴표 사용이 주요 문제입니다. Bash Reference Manual 에 따르면 :

작은 따옴표 ( ')로 문자를 묶으면 따옴표 안에있는 각 문자의 리터럴 값이 유지됩니다. 백 슬래시가 앞에있는 경우에도 작은 따옴표 사이에 작은 따옴표를 사용할 수 없습니다. [...] 따옴표 둘러싸 자 ( ")를 제외한 시세 내의 모든 문자의 리터럴 값을 보존하고 $, `, \, 및, 기록 팽창이 활성화되면 !. 문자 $와`는 큰 따옴표로 묶인 특별한 의미를 유지합니다 (셸 확장 참조). 다음 문자 중 하나 다음에 할 때 백 슬래시는 특별한 의미를 유지 : $, `, ",\, 또는 개행. 큰 따옴표 내에서 이러한 문자 중 하나가 뒤에 오는 백 슬래시가 제거됩니다. 특별한 의미가없는 문자 앞의 백 슬래시는 수정되지 않은 상태로 남습니다. 큰 따옴표 앞에 백 슬래시를 붙여 큰 따옴표로 묶을 수 있습니다. 활성화 된 경우 !큰 따옴표로 표시된 부분이 백 슬래시를 사용하여 이스케이프 되지 않는 한 히스토리 확장이 수행됩니다 . 앞의 백 슬래시 !는 제거되지 않습니다. 특수 매개 변수 *와는 @큰 따옴표 (쉘 변수 확장 참조) 할 때 특별한 의미를 가지고있다.

질문에서 묻는 특정 경우에서 $ COLUMNS는 비표준 속성을 갖는 특수 변수입니다 (위의 lhunath의 답변 참조).


20
작은 따옴표의 경우이 해결 방법이 도움이 될 수 있습니다. 'before'"$variable"'after'(이 답변에 명시된대로 : stackoverflow.com/a/13802438/2254346 )
MakisH

좋은 대답! 작은 따옴표로 env 변수를 참조하는 것과 동일한 문제가 있습니다. 작은 따옴표를 큰 따옴표로 변경하면 내 env 변수가 예상대로 확장되었습니다.
Binita Bharati

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;-) 에서 멀리 떨어져 있어야합니다. )


정보 주셔서 감사합니다; 무슨 일이 일어나고 있는지 아는 것은 문제에 카타르시스 감각을 가져옵니다.
Jamie

2

다음 스크립트는 $COLUMNS. COLUMNS이 통화 전에 설정하지 않았는지 궁금합니다 .

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

$COLUMNS스크립트 내부에서 반향 하여 올바르게 설정되었는지 확인할 수 있습니까?


Boo, hiss re : unquoted- $@단일 매개 변수 "two words"를 두 개의 개별 매개 변수로 분할 two하고 words. "$@"인수 목록을 주어진 그대로 전달 해야합니다 .
Charles Duffy

0

당신이 올바르게하고 있으므로 다른 문제가 있다고 생각합니다 (COLUMNS를 내 보내지 않습니까?).

이러한 경우를 디버깅하는 트릭은 특수 명령을 만드는 것입니다 (프로그래밍 언어 사용자를위한 클로저). 다음을 수행하여 diff-columns라는 셸 스크립트를 만듭니다.

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

그리고 그냥 사용

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

이렇게하면 코드가 더 깨끗하고 모듈 식 (하향식 접근 방식)이 더 깔끔해지며 diff-columns 코드를 개별적으로 테스트 할 수 있습니다 (상향식 접근 방식).


명령 줄은 프로세스가 분기되기 전에 구문 분석되므로 COLUMNS를 내 보내지 않는 것이 문제가 될 수 없습니다.
Peter van der Heijden

1
그는 bash 스크립트의 일부로 자신의 코드를 말하므로 문제가 될 수 있습니다.
Colas Nahaboo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.