![sed: 문자열을 변수 내용으로 교체](https://linux55.com/image/128344/sed%3A%20%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84%20%EB%B3%80%EC%88%98%20%EB%82%B4%EC%9A%A9%EC%9C%BC%EB%A1%9C%20%EA%B5%90%EC%B2%B4.png)
{?varname}
특정 패턴( )의 문자열을 찾아 해당 환경 변수로 바꾸는 스크립트를 작성하려고 합니다 .
이것이 내가 지금까지 가지고 있는 것입니다:
function get_env() {
var=$1
echo ${!var}
}
sed -e 's/{?\([a-z]*}\)/'$(get_env '\1')'/g' file.txt
이 함수는 다음과 같이 작동합니다 get_env LOGNAME
-->dotan
echo __$1__
sed는 함수의 값을 반환합니다. 예를 들어 함수의 내용을 I will get 으로 바꾸면 {?logname}
-->__LOGNAME__
그러나 결합하면 작동하지 않습니다. 이는 함수가 항상 빈 문자열을 반환하는 것과 같습니다.
여기서 문제의 원인이 무엇인지 잘 모르겠습니다. 어떤 아이디어가 있나요?
답변1
명령줄은 get_env '\1'
명령 대체에서 실행되며 해당 출력은 에 붙여넣어집니다 . 변수의 유효한 이름이 아니므 sed
로 오류가 발생할 수 있습니다 .\1
s/\{\?([a-z]+)\}/$ENV{$1}/
Perl을 사용하여 이를 수행 할 수 있습니다 . %ENV
이는 환경 변수를 포함하는 해시입니다.
$ export name=you
$ echo "hello {?name}" | perl -pe 's/\{\?([a-z]+)\}/$ENV{$1}/'
hello you
(GNU sed에는 e
외부 프로그램을 실행하는 명령이 있지만 일치하는 부분만이 아닌 전체 패턴 공간을 실행하기 때문에 여기에는 적합하지 않은 것 같습니다.)
순전히 Bash에서 ( )를 주장한다면 setvar.sh
:
#!/bin/bash
while IFS= read -r line ; do
while [[ $line =~ ^(.*)(\{\?[a-zA-Z0-9_]+\})(.*)$ ]] ; do
varname=${BASH_REMATCH[2]}
varname=${varname#"{?"}
varname=${varname%\}}
printf -v line "%s%s%s" "${BASH_REMATCH[1]}" "${!varname}" "${BASH_REMATCH[3]}"
done
printf "%s\n" "$line"
done < "${1-/dev/stdin}"
$ echo 'foo {?BASH_VERSION} {?blah} bar' |blah=ABC bash setvar.sh
foo 4.4.12(1)-release ABC bar
답변2
이것이 내가 생각해낸 해결책이다
grep -o '{?\S*}' file.txt | sed 's/{?\(.*\)}/\1/' | xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"
그것을 파괴:
grep -o '{?\S*}' file.txt
- 대체할 모든 변수를 가져옵니다.sed 's/{?\(.*\)}/\1/'
- 형식 제거xargs -I {} sh -c "sed -i -e 's/{?"{}"}/'$"{}"'/' file.txt"
- 각 변수를 개별적으로 검색하고 교체