Development Tip

복잡한 텍스트 파일에서 쉘 변수를 대체하는 방법

yourdevel 2020. 12. 9. 21:50
반응형

복잡한 텍스트 파일에서 쉘 변수를 대체하는 방법


쉘 변수 (예 : $ VAR1 또는 $ VAR2)를 도입 한 여러 텍스트 파일이 있습니다.

해당 파일 (하나씩)을 가져 와서 모든 변수가 교체 된 새 파일에 저장하고 싶습니다.

이를 위해 다음 셸 스크립트 (StackOverflow에 있음)를 사용했습니다.

while read line
do
    eval echo "$line" >> destination.txt
done < "source.txt"

이것은 매우 기본적인 파일에서 매우 잘 작동합니다.

그러나 더 복잡한 파일에서는 "eval"명령이 너무 많은 작업을 수행합니다.

  • "#"로 시작하는 줄은 건너 뜁니다.

  • XML 파일 구문 분석으로 인해 많은 오류가 발생합니다.

더 나은 방법이 있습니까? (쉘 스크립트에서 ... 예를 들어 Ant로 쉽게 수행된다는 것을 알고 있습니다)

종류 안부


내 시스템 envsubst에 gettext-base 패키지의 일부인 명령이 있습니다.

따라서 다음과 같이 쉽게 할 수 있습니다.

envsubst < "source.txt" > "destination.txt"

답변 2와 관련하여 envsubst에 대해 논의 할 때 "내 .sh 스크립트에 선언 된 변수로 어떻게 작동하도록 할 수 있습니까?"라고 물었습니다.

대답은 envsubst를 호출하기 전에 변수를 내보내기 만하면된다는 것입니다.

envsubst SHELL_FORMAT 인수를 사용하여 입력에서 바꾸려는 변수 문자열을 제한 할 수도 있습니다 (입력에서 문자열이 의도하지 않은 공통 쉘 변수 값 (예 : $ HOME)로 대체되는 것을 방지).

예를 들면 :

export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'

envsubst "$MYVARS" <source.txt >destination.txt

source.txt의 $ VAR1 및 $ VAR2 (및 VAR1 및 VAR2 만)의 모든 인스턴스를 각각 'somevalue'및 'someothervalue'로 바꿉니다.


이 주제가 오래되었다는 것을 알고 있지만 변수를 내 보내지 않고도 더 간단한 작업 솔루션이 있습니다. oneliner가 될 수 있지만 \온라인 끝을 사용하여 분할하는 것을 선호합니다 .

var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"

#         ^^^^^^^^^^^    ^^^^^^^^^^     ^^^^^^^^^^^^^^^
# define which to replace   input            output

변수 envsubst는 환경 변수로 간주되기 위해 동일한 행에 정의되어야합니다 .

'$var1,$var3'오직 지정된 사람을 대체 할 선택 사항입니다. ${VARIABLE_USED_BY_JENKINS}대체해서는 안되는 입력 파일을 상상해보십시오 .


  1. ENV 변수 정의
$ export MY_ENV_VAR=congratulation
  1. 다음 내용으로 템플릿 파일 ( in.txt ) 만들기
$MY_ENV_VAR

(리눅스에서) $ TERM, $ SHELL, $ HOME ...과 같이 시스템에서 정의한 다른 모든 ENV 변수를 사용할 수도 있습니다.

  1. 이 명령을 실행하여 in.txt 파일의 모든 환경 변수를 raplace 하고 결과를 out.txt에 씁니다.
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
  1. out.txt 파일 내용 확인
$ cat out.txt

"축하합니다"가 표시됩니다.


실제로 백 슬래시를 무시 하도록 변경해야 read합니다 read -r.

또한 따옴표와 백 슬래시를 이스케이프해야합니다. 그래서

while read -r line; do
  line="${line//\\/\\\\}"
  line="${line//\"/\\\"}"
  line="${line//\`/\\\`}"
  eval echo "\"$line\""
done > destination.txt < source.txt

그래도 확장을 수행하는 끔찍한 방법입니다.


필요한 모든 변수를 내 보낸 다음 perl onliner를 사용하십시오.

TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1} // $& #ge;')

그러면 TEXT에있는 모든 ENV 변수가 실제 값으로 바뀝니다. 인용문도 보존됩니다. :)


정말로 bash (및 sed)를 사용하고 싶다면 각 환경 변수 ( setposix 모드에서 반환 됨 )를 살펴보고 -e 'regex'sed로 끝나는 sed 묶음을 빌드 한 -e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'다음 모든 것을 전달합니다. sed.

Perl은 더 좋은 작업을 수행 할 수 있지만 환경 변수에 배열로 액세스 할 수 있고 실행 가능한 대체를 수행 할 수 있으므로 환경 변수를 한 번만 일치시킬 수 있습니다.


envsubst내가 사용하고 싶은 것과 똑같은 것 같지만 -v옵션이 조금 놀랐습니다.

While envsubst < template.txt was working fine, the same with option -v was not working:

$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
$ envsubst -V
envsubst (GNU gettext-runtime) 0.18.2
Copyright (C) 2003-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.

As I wrote, this was not working:

$ envsubst -v < template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments

I had to do this to make it work:

TEXT=`cat template.txt`; envsubst -v "$TEXT"

Maybe it helps someone.

참고URL : https://stackoverflow.com/questions/14155596/how-to-substitute-shell-variables-in-complex-text-files

반응형