sed에서 환경 변수 대체


202

스크립트에서 이러한 명령을 실행하면

#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla

그것은 괜찮습니다.

그러나 내가 달리면 :

#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s' 

튜토리얼에서 쉘에서 환경 변수를 대체하고 중지 해야하는 $varname부분을 인용하여 직접 대체하지 않도록 부품을 인용 합니다. 이것은 내가 한 일이며 변수가 바로 정의 된 경우에만 작동합니다.

$var쉘에 정의 된 환경 변수로 sed를 어떻게 인식 할 수 있습니까?


4
$ PWD에는 /가 포함되어 있으며 이는 대체 명령을 종료합니다.
derobert

@derobert : tnx. 솔루션 중 하나가이 문제를 해결합니다.
RomanM

4
set -x쉘이 각 명령을 실행하기 직전에 에코하도록하려면 쉘에서 사용하십시오 . 이것은 많은 혼란을 제거 할 수 있습니다. (또한, 종종 set -u참조 해제 된 변수 해제를 어려운 오류로 만들기 위해 사용 합니다. (참조 set -e).)
bobbogo

나는, 프로세스 테이블에 값을 누출하지로 환경 변수를 처리하기 위해 나오지있는 방법을 찾으려 한 것 같다 모두에이 글의 답변에 따라 비밀 설치에 대한 잘못된 도구입니다 나오지도
ThorSummoner

답변:


302

두 예제가 동일 해 보이므로 문제를 진단하기가 어렵습니다. 잠재적 인 문제 :

  1. 다음과 같이 큰 따옴표가 필요할 수 있습니다. sed 's/xxx/'"$PWD"'/'

  2. $PWD슬래시를 포함 할 수 있으며,이 경우 구분자로 사용하기 위해 포함 되지 않은 문자를 찾아야합니다 $PWD.

한 번에 두 문제를 모두 해결하려면

sed 's@xxx@'"$PWD"'@'

그러나 어떤 문자를 사용할 수 있는지 확실하게 경로 이름에 나타나지 않습니까?
RomanM

5
@ # %와 같은 여러 후보를 가질 수 있습니다! $ PWD에 케이스 표현식이 있는지 확인하십시오. 예를 들어, @의 사례 "$ PWD" ) ;; *) delim = "@";; esac; $ delim이 비어 있지 않을 때까지 반복하십시오.
Norman Ramsey

큰 따옴표 대신 다른 대안이 있습니다. 아래 답변을 참조하십시오 .
Thales Ceolin

sed에 다른 구분 기호를 사용할 수 있습니다. 환경 변수가 URL 인 경우 /를 사용할 필요가 없습니다.
구첼 카벤

123

Norman Ramsey의 답변 외에도 전체 문자열을 큰 따옴표로 묶을 수 있습니다 (문을 더 읽기 쉽고 오류가 덜 발생하게 만들 수 있음).

따라서 'foo'를 검색하여 $ BAR의 내용으로 바꾸려면 sed 명령을 큰 따옴표로 묶을 수 있습니다.

sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"

첫 번째, $ BAR은 올바르게 확장되지 않지만 두 번째 $ BAR은 올바르게 확장됩니다.


4
이 등 큰 따옴표, 작은 따옴표 덤비는 것보다 깨끗
Vladislavs Dovgalecs

이것은이 명령에서 환경 변수를 올바르게 확장하기 위해 사용해야하는 것입니다. sed -i "s / 127.0.0.1 / 127.0.0.1 localhost $ HOSTNAME /"hosts
izikandrw

2
이 깔끔하지만 당신과 같은 좀 더 복잡한 치환을 수행 할 때이 작동하지 않는 "2,$s/^/$foo/"$s너무 변수로 해석됩니다 및 그것은 안된다.
mjp

59

"/"이외의 다른 문자를 대신 사용할 수 있습니다.

sed "s#$1#$2#g" -i FILE

필자의 경우 $ 2는 파일 경로이므로 $ 2의 내용 sed을 해석하여 바프되었습니다 /. 이것은 내가 그것을 지나가는 데 필요한 것입니다. 좋은 팁 주셔서 감사합니다!
보이드 헴힐

54

또 다른 쉬운 대안 :

때문에 $PWD일반적으로 슬래시를 포함 /, 사용 |대신 /나오지 문 :

sed -e "s|xxx|$PWD|"

4
"큰 따옴표를 사용하는 대안"이라고 말했지만 예에서 큰 따옴표를 사용합니까?
Jeach

요점은 바로 큰 따옴표를 사용하지 않는다는 것입니다 $PWD...?
Christian

14

질문을 편집하면 문제가 발생합니다. 현재 디렉토리가 /home/yourname ...이 경우 아래 명령 이라고 가정 해 봅시다 .

sed 's/xxx/'$PWD'/'

로 확장됩니다

sed `s/xxx//home/yourname//

유효하지 않습니다. 이렇게하려면 $ PWD에서 \각 문자 앞에 문자 를 넣어야합니다 /.


그러나 PWD는 쉘에 의해 정의됩니다 ... 내가 $ PWD를 에코하면 pwd를 얻습니다
RomanM

1
그렇다면 환경 변수를 어떻게 피할 수 있습니까?
einpoklum

1
선택한 답변은 해결 방법을 설명합니다 ... 구분 기호에 슬래시를 사용하지 마십시오
Eddie

현재 작업 디렉토리에 다른 문자가 포함되면 문제가됩니다.
blubberdiblub

6

나쁜 방법 : 구분 기호 변경

sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's@xxx@'"$PWD"'@'

아마 최종 답변이 아닌 사람들은

$PWD, / :OR 에서 어떤 캐릭터가 나타날지 알 수 없습니다 @.

좋은 방법은의 특수 문자를 바꾸는 것입니다 $PWD.

좋은 방법 : 탈출 구분 기호

예를 들어 : URL$ url 로 바꾸십시오 ( : /내용이 있음).

x.com:80/aa/bb/aa.js

문자열 $ tmp에서

<a href="URL">URL</a>

ㅏ. /구분자로 사용

echo ${url//\//\\/}
x.com:80\/aa\/bb\/aa.js

echo ${url//\//\/}
x.com:80/aa/bb/aa.js

echo "${url//\//\/}"
x.com:80\/aa\/bb\/aa.js

echo $tmp | sed "s/URL/${url//\//\\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

echo $tmp | sed "s/URL/${url//\//\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

또는

비. :구분 기호로 사용 (보다 읽기 쉬운 /)

echo ${url//:/\:}
x.com:80/aa/bb/aa.js

echo "${url//:/\:}"
x.com\:80/aa/bb/aa.js

echo $tmp | sed "s:URL:${url//:/\:}:g"
<a href="x.com:80/aa/bb/aa.js">x.com:80/aa/bb/aa.js</a>

3

실제로 가장 간단한 방법은 적어도 sed replacement (s) 명령에 다른 구분 기호를 사용하는 것입니다. 따라서 s / pattern / '$ mypath'/를 s / pattern // my / path /로 확장하는 대신 s 명령을 혼동 시키려면 s! pattern! '$ mypath'를 사용하십시오! s! pattern! / my / path로 확장됩니다! 나는 Bang (!) 문자 (또는 원하는 것을 사용)를 사용하여 일반적인 구분을 의미하지만 슬래시를 구분 기호로 사용하지 않습니다.


3
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 

여기서 VAR은 필드를 바꾸려는 것을 포함합니다.


3

sed 내에서 변수 다루기

[root@gislab00207 ldom]# echo domainname: None > /tmp/1.txt

[root@gislab00207 ldom]# cat /tmp/1.txt

domainname: None

[root@gislab00207 ldom]# echo ${DOMAIN_NAME}

dcsw-79-98vm.us.oracle.com

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g'

 --- Below is the result -- very funny.

domainname: ${DOMAIN_NAME}

 --- You need to single quote your variable like this ... 

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g'


--- The right result is below 

domainname: dcsw-79-98vm.us.oracle.com

Azure DevOps YAML 파이프 라인에서이 작업을 수행하기 위해 고심하고있었습니다. 이 의견은이 트릭을 사용하여 일부 구성 파일을 토큰 화하는 데 도움이되었습니다.
andov

1

비슷한 문제가 있었고 목록이 있었고 템플릿을 기반으로하는 SQL 스크립트를 작성 @INPUT@해야합니다 (바꿀 요소로 포함 ).

for i in LIST 
do
    awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.