여러 줄 문자열과 문자열 보간을 처리하는 방법은 무엇입니까?

여러 줄 문자열과 문자열 보간을 처리하는 방법은 무엇입니까?

어딘가에 여러 줄 문자열에 대한 템플릿을 갖고 싶다고 가정해 보겠습니다.

I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}

자리 표시자를 사용자 입력으로 바꾸는 가장 좋은 방법은 무엇입니까? 여기에 있는 문서가 유용합니까?

답변1

\<newline> 또는 문자 , , 또는 가 [a] 여러 줄 문자열 에 사용되지 않거나 올바르게 인용되었다고 가정하면 이 문서(및 변수)가 최선의 선택입니다.\$`

#!/bin/sh

placeholders="value one"
different="value two"
here="value three"
there="value four"

cat <<-_EOT_
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}.
_EOT_

실행되는 경우:

$ sh ./script
I have some
text with value one
in this and some value two
ones value three and value four.

물론 qouting을 올바르게 사용하면 변수도 작동합니다.

$ multilinevar='I have some
> text with '"${placeholders}"'
> in this and some '"${different}"'
> ones '"${here}"' and '"${there}"'.'
$ echo "$multilinevar"
I have some
text with value one
in this and some value two
ones value three and value four.

두 솔루션 모두 여러 줄의 변수 자리 표시자를 허용할 수 있습니다.


[a] 매뉴얼에서:

...문자 시퀀스 \<newline>은 무시되며 \는 \, $ 및 ` 문자를 인용하는 데 사용해야 합니다. ...

답변2

bash에서 이를 수행하는 한 가지 방법이 있습니다. 여기서는 연관 배열을 사용하므로 최신 버전이 필요합니다.

template=$(cat << 'END_TEMPLATE'
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}
END_TEMPLATE
)

mapfile -t placeholders < <(grep -Po '(?<=\$\{).+?(?=\})' <<< "$template" | sort -u)

declare -A data
for key in "${placeholders[@]}"; do
    read -p "Enter the '$key' value: " -r data[$key]
done

t=$template
while [[ $t =~ '${'([[:alnum:]_]+)'}' ]]; do
    t=${t//"${BASH_REMATCH[0]}"/"${data[${BASH_REMATCH[1]}]}"}
    #      ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    #      |                    + the value the user entered
    #      + the placeholder in the text
done

echo "$t"

답변3

사용자 입력이 주어지면 one, two,three

다음 명령은 ${placeholder}제공된 모든 인스턴스를 입력으로 바꿉니다.

sed -i 's/${placeholders}/one/g; s/${different}/two/g; s/${here}/three/g' yourTemplateFile

이것을 bash 스크립트에서 사용하고 쉘 변수에 사용자 입력을 입력하면 하나의 명령으로 모든 대체가 수행됩니다.

답변4

다음 스크립트를 사용하여 테스트했으며 정상적으로 작동했습니다.

echo "enter count of userinput required"
read c
for ((i=1;i<=$c;i++))
do
echo "enter the values"
read input_$i
done

awk -v i="$input_1" -v j="$input_2" -v k="$input_3" -v l="$input_4"   '{gsub(/\${placeholders}/,i,$0);gsub(/\${different}/,j,$0);gsub(/\${here}/,k,$0);gsub(/\${there}/,l,$0);print $0}' filename >>filename_tmp && mv filename_tmp filename

관련 정보