텍스트 파일에서 ${} 자리 표시자를 바꾸려면 어떻게 해야 합니까?
파일의 을 MySQL에 .MySQL은 "템플릿"입니다.MySQL은 "템플릿" 에는 "" "MySQL" "MySQL" "MySQL" "MySQL" "MySQL" 등의 .${dbName}
표준 유틸리티는 입니까?이러한 인스턴스를 대체하고 출력을 표준 출력으로 덤프하기 위한 명령줄 유틸리티는 무엇입니까?
입력 파일은 안전한 것으로 간주되지만 잘못된 대체 정의가 존재할 수 있습니다.교환을 실행하면 의도하지 않은 코드 실행을 방지할 수 있습니다.
갱신하다
다음은 $VAR 또는 ${VAR}와 같은 변수만 대체하고 간략하게 설명하는 유사한 질문에 대한 yottatsa의 해결 방법입니다.
i=32 word=foo envsubst < template.txt
물론 저와 워드가 당신의 환경에 있다면 그건 그냥
envsubst < template.txt
Mac에서는 MacGPG2에서 gettext의 일부로 설치된 것처럼 보입니다.
오래된 답변
여기 같은 질문에 대한 mogsie의 해결책에 대한 개선점이 있습니다. 제 해결책에서는 큰따옴표는 필요 없습니다. mogsie의 것은 필요하지만, 그의 것은 하나의 라이너입니다.
eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null
이 두 솔루션의 장점은 백슬래시는 이스케이프 문자이지만 보통 $(...), ..., $(...)가 아닌 몇 가지 유형의 셸 확장만 얻을 수 있다는 것입니다.단, 여기서 백슬래시는 이스케이프 문자이지만 파싱에 버그가 있고 여러 행이 정상적으로 처리됩니다.
세드!
지정된 템플릿txt:
번호는 ${i}입니다.단어는 ${word}입니다.
이렇게 말할 수밖에 없어
sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt
Jonathan 에게 여러 Jonathan Leffler를 할 수 합니다.-e
「」에 인수sed
★★★★★★ 。
/bin/sh
변수를 설정하는 작은 셸 스크립트를 작성한 후 셸 자체를 사용하여 템플릿을 해석합니다.이와 같이(새 행을 올바르게 처리하도록 편집):
파일 템플릿txt:
the number is ${i}
the word is ${word}
파일 스크립트sh:
#!/bin/sh
#Set variables
i=1
word="dog"
#Read in template one line at the time, and replace variables (more
#natural (and efficient) way, thanks to Jonathan Leffler).
while read line
do
eval echo "$line"
done < "./template.txt"
출력:
#sh script.sh
the number is 1
the word is dog
최근 관심을 가지고 다시 생각해 봤는데, 원래 생각하고 있던 툴은 오토툴용 매크로 프로세서였던 것 같습니다.처음에 지정한 변수 대신 다음을 사용합니다.
$echo 'I am a DBNAME' | m4 -DDBNAME="database name"
rendertemplate.sh
:
#!/usr/bin/env bash
eval "echo \"$(cat $1)\""
★★★★★★★★★★★★★★★★★.template.tmpl
:
Hello, ${WORLD}
Goodbye, ${CHEESE}
템플릿 렌더링:
$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl
Hello, Foo
Goodbye, Bar
템플릿입니다.txt
Variable 1 value: ${var1}
Variable 2 value: ${var2}
data.sh
#!/usr/bin/env bash
declare var1="value 1"
declare var2="value 2"
parser.sh
#!/usr/bin/env bash
# args
declare file_data=$1
declare file_input=$2
declare file_output=$3
source $file_data
eval "echo \"$(< $file_input)\"" > $file_output
./파서.sh 데이터sh 템플릿txt parseed_file 입니다.txt
parsed_file 입니다.txt
Variable 1 value: value 1
Variable 2 value: value 2
다음은 이전 답변을 기반으로 한 perl을 사용한 솔루션으로 환경 변수를 대체합니다.
perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile
여기 강력한 Bash 함수가 있습니다. 사용 중임에도 불구하고eval
할 것입니다 - 사용하기에 안전할 것입니다.
★★★★★${varName}
입력 텍스트의 변수 참조는 호출 셸의 변수에 따라 확장됩니다.
그 외 확장되는 것은 없습니다.이름에 둘러싸이지 않은 변수 참조도 없습니다.{...}
:$varName
치환명령어 치환)도 $(...)
구문 " " " "`...`
치환 , )은 사용할 수 없습니다.$((...))
구문 " " " "$[...]
를 참조해 주세요.
의 를 하다$
로서 「」라고 하는 \
: :\${HOME}
입력은 stdin을 통해서만 허용됩니다.
예:
$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)
함수 소스 코드:
expandVarsStrict(){
local line lineEscaped
while IFS= read -r line || [[ -n $line ]]; do # the `||` clause ensures that the last line is read even if it doesn't end with \n
# Escape ALL chars. that could trigger an expansion..
IFS= read -r -d '' lineEscaped < <(printf %s "$line" | tr '`([$' '\1\2\3\4')
# ... then selectively reenable ${ references
lineEscaped=${lineEscaped//$'\4'{/\${}
# Finally, escape embedded double quotes to preserve them.
lineEscaped=${lineEscaped//\"/\\\"}
eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
done
}
는 no no no no no no no 라고 가정합니다.0x1
,0x2
,0x3
, , , , 입니다.0x4
이러한 문자는 내부적으로 사용되기 때문에 제어 문자는 입력에 존재하며 함수가 텍스트를 처리하므로 안전한 가정이어야 합니다.
Sigil과 같은 것을 사용하는 것을 추천합니다.https://github.com/gliderlabs/sigil
1개의 바이너리로 컴파일 되어 있기 때문에, 시스템에의 인스톨이 매우 간단합니다.
그런 다음 다음과 같은 간단한 원라이너를 수행할 수 있습니다.
cat my-file.conf.template | sigil -p $(env) > my-file.conf
하다, 안전하다, 안전하다, 안전하다, 안전하다, 안전하다.eval
regex를 사용하는 보다 더 할 수 있습니다.sed
여기에서는 큰따옴표 사이에 파일의 내용이 입력된 것처럼 셸이 대체 작업을 수행하도록 하는 방법을 보여 줍니다.
템플릿의 예를 사용합니다.txt(내용 포함):
The number is ${i}
The word is ${word}
다음 행은 셸이 템플릿의 내용을 삽입하는 원인이 됩니다.txt를 입력하고 결과를 표준으로 작성합니다.
i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'
설명:
i
★★★★★★★★★★★★★★★★★」word
되며, 는 환경변수로 된다.sh
.sh
는 전달된 문자열의 내용을 실행합니다.- 서로 옆에 쓰여진 문자열은 하나의 문자열이 됩니다.이 문자열은 다음과 같습니다.
echo "
" + "$(cat template.txt)
+' " + ""
- 치환의 범위는 다음과 같기 때문에
"
" , "$(cat template.txt)
는 "의 .cat template.txt
. - 이 되었습니다.
sh -c
다음과 같이 됩니다.echo "The number is ${i}\nThe word is ${word}"
,- 서 ''는
i
★★★★★★★★★★★★★★★★★」word
는 지정된 환경변수입니다.
Perl을 사용할 의향이 있다면 제안하겠습니다.SED 및/또는 AWK 전문가 중에는 훨씬 쉬운 방법을 알고 있는 사람도 있을 것입니다.교체용 dbName뿐만 아니라 더 복잡한 매핑이 있는 경우 이 매핑을 쉽게 확장할 수 있지만 이 시점에서 표준 Perl 스크립트에 넣는 것이 좋습니다.
perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql
조금 더 복잡한 작업을 수행하기 위한 짧은 Perl 스크립트(복수 키 처리):
#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;
위의 스크립트에 replace-script 라고 이름을 붙이면 다음과 같이 사용할 수 있습니다.
replace-script < yourfile | mysql
file.tpl:
The following bash function should only replace ${var1} syntax and ignore
other shell special chars such as `backticks` or $var2 or "double quotes".
If I have missed anything - let me know.
script.sh:
template(){
# usage: template file.tpl
while read -r line ; do
line=${line//\"/\\\"}
line=${line//\`/\\\`}
line=${line//\$/\\\$}
line=${line//\\\${/\${}
eval "echo \"$line\"";
done < ${1}
}
var1="*replaced*"
var2="*not replaced*"
template file.tpl > result.txt
저도 같은 생각을 하다가 이 실을 발견했어요.(백틱에 주의해서) 이 일을 하게 된 계기가 되었습니다.
$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
선택의 여지가 많긴 하지만, 난 내 물건을 더미 위에 던져야겠다고 생각했어.perl 기반이며 ${...} 형식의 대상 변수만 인수로 처리되는 파일을 stdout에 출력합니다.
use Env;
Env::import();
while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }
print "$text";
물론 저는 펄을 좋아하는 사람이 아니기 때문에 치명적인 결함이 있을 수 있습니다(단, 저는 문제가 없습니다).
컨피규레이션파일 형식을 제어할 수 있는 경우 bash 자체에서 실행할 수 있습니다.컨피규레이션파일의 서브셸이 아닌 소스("")만 있으면 됩니다.이를 통해 변수가 서브셸이 아닌 현재 셸의 컨텍스트에서 생성되고 계속 존재하게 됩니다(서브셸이 종료될 때 변수가 사라집니다.
$ cat config.data
export parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA
export parm_user=pax
export parm_pwd=never_you_mind
$ cat go.bash
. config.data
echo "JDBC string is " $parm_jdbc
echo "Username is " $parm_user
echo "Password is " $parm_pwd
$ bash go.bash
JDBC string is jdbc:db2://box7.co.uk:5000/INSTA
Username is pax
Password is never_you_mind
컨피규레이션파일이 셸 스크립트가 될 수 없는 경우 실행 전에 컴파일만 하면 됩니다(컴파일은 입력 포맷에 따라 다릅니다).
$ cat config.data
parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA # JDBC URL
parm_user=pax # user name
parm_pwd=never_you_mind # password
$ cat go.bash
cat config.data
| sed 's/#.*$//'
| sed 's/[ \t]*$//'
| sed 's/^[ \t]*//'
| grep -v '^$'
| sed 's/^/export '
>config.data-compiled
. config.data-compiled
echo "JDBC string is " $parm_jdbc
echo "Username is " $parm_user
echo "Password is " $parm_pwd
$ bash go.bash
JDBC string is jdbc:db2://box7.co.uk:5000/INSTA
Username is pax
Password is never_you_mind
특정의 경우, 다음과 같은 것을 사용할 수 있습니다.
$ cat config.data
export p_p1=val1
export p_p2=val2
$ cat go.bash
. ./config.data
echo "select * from dbtable where p1 = '$p_p1' and p2 like '$p_p2%' order by p1"
$ bash go.bash
select * from dbtable where p1 = 'val1' and p2 like 'val2%' order by p1
그런 다음 go.bash의 출력을 MySQL 및 voila에 파이프합니다.데이터베이스 :-)를 파괴하지 않기를 바랍니다.
백업을 사용하여 여러 파일을 편집할 수 있습니다.
perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
-i.orig \
-p config/test/*
라는 이름의 셸템플릿 스크립트를 작성했습니다.나의shtpl
이제 ansible을 많이 사용하기 때문에 다음과 같은 구문을 사용할 수 있습니다.
$ cat /tmp/test
{{ aux=4 }}
{{ myarray=( a b c d ) }}
{{ A_RANDOM=$RANDOM }}
$A_RANDOM
{% if $(( $A_RANDOM%2 )) == 0 %}
$A_RANDOM is even
{% else %}
$A_RANDOM is odd
{% endif %}
{% if $(( $A_RANDOM%2 )) == 0 %}
{% for n in 1 2 3 $aux %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/passwd field #$n: $(grep $USER /etc/passwd | cut -d: -f$n)
{% endfor %}
{% else %}
{% for n in {1..4} %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/group field #$n: $(grep ^$USER /etc/group | cut -d: -f$n)
{% endfor %}
{% endif %}
$ ./shtpl < /tmp/test
6535
6535 is odd
$myarray[0]: a
/etc/group field #1: myusername
$myarray[1]: b
/etc/group field #2: x
$myarray[2]: c
/etc/group field #3: 1001
$myarray[3]: d
/etc/group field #4:
내 gitub에 대한 자세한 정보
이 솔루션은 가장 쉽고 강력한 솔루션이며, 같은 명령어를 사용하여 다른 템플릿을 포함할 수도 있습니다.eval echo "$(<template.txt)
:
중첩된 템플릿을 사용한 예제
- 템플릿 파일을 만듭니다.변수는 일반 bash 구문입니다.
${VARIABLE_NAME}
또는$VARIABLE_NAME
특수 캐릭터에서 벗어나야 합니다.
\
당신의 템플릿에서 그것들은 해석될 다른 것들로eval
.
template.txt
Hello ${name}!
eval echo $(<nested-template.txt)
nested-template.txt
Nice to have you here ${name} :\)
- 소스 파일 생성
template.source
declare name=royman
- 템플릿을 해석하다
source template.source && eval echo "$(<template.txt)"
- 산출량
Hello royman!
Nice to have you here royman :)
환경
다른 것은 사용하지 말아 주세요(즉, 사용하지 말아 주세요).eval
)
언급URL : https://stackoverflow.com/questions/415677/how-to-replace-placeholders-in-a-text-file
'programing' 카테고리의 다른 글
여러 줄 명령어 입력 방법 (0) | 2023.04.23 |
---|---|
특정 확장자를 가진 모든 파일을 루프합니다. (0) | 2023.04.19 |
WPF에서 수식자 키 상태를 검출하려면 어떻게 해야 합니까? (0) | 2023.04.19 |
나머지 파일을 수정하지 않고도 하나의 Excel 파일 워크시트(탭)를 읽고 수정할 수 있습니까? (0) | 2023.04.19 |
Django에서 여러 개체를 ManyToMany 관계에 한 번에 추가하는 방법 (0) | 2023.04.19 |