file
다음이 있다고 가정해 보겠습니다 .
var1='a random text'
var2='another random text'
var3='a third random text'
eval
이와 같은 명령을 사용하면 이러한 모든 변수가 쉘에 직접 저장된다는 것을 알고 있습니다.
$ eval $(cat file)
이렇게 하면 내 쉘이 $var1
, $var2
및 $var3
해당 내용을 생성합니다. 이를 알고 있으면 다음과 같이 JSON을 수동으로 생성할 수 있습니다.
$ JSON="{ \"var1\" : \"$var1\", \"var2\" : \"$var2\", \"var3\" : \"$var3\"}"
그러면 유효한 JSON이 생성됩니다.
$ echo $JSON
{ "var1" : "a random text", "var2" : "another random text", "var3" : "a third random text"}
여기서 문제는 var1, var2 및 var3 키를 하드코딩했다는 것입니다. 제 경우에는 파일이 더 크고 더 많은 변수를 저장할 수 있습니다(var1, var2 및 var3뿐만 아니라). 셸에 파일 변수를 저장하는 것처럼 명령줄을 사용하여 이 작업을 수행하는 쉬운 방법이 있는지 궁금했지만 eval
변수를 저장하는 대신 JSON 출력을 생성했습니다. 가능합니까? 명령줄을 사용하여 비슷한 구조의 파일을 JSON으로 직접 변환할 수 있나요?
나의 대체 솔루션은 해당 파일에서 문자별로 실행되는 코드(셸을 사용하지 않고)를 개발한 다음 루프에서 모든 것을 동적으로 분리하는 것입니다. 하지만 제가 이 질문을 하는 이유는 솔루션을 지나치게 복잡하게 만드는 것을 피하고 싶기 때문입니다.
답변1
조합 사용 jo
(여기) 및 jq
(에서여기) 셸 변수를 생성하지 않거나 셸이 파일을 전혀 해석하지 않도록 합니다.
jo <file |
jq --arg sq "'" '.[] |= ( ltrimstr($sq) | rtrimstr($sq) )'
이는 jo
JSON 문서를 생성하는 데 처음 사용됩니다.
{
"var1": "'a random text'",
"var2": "'another random text'",
"var3": "'a third random text'"
}
(그러나 한 줄에). 이는 파일의 변수 할당을 키-값 쌍으로 해석하여 수행됩니다.
그런 다음 이 jq
도구를 사용하여 각 값의 시작과 끝 부분에 있는 작은따옴표를 제거합니다.
최종 결과는
{
"var1": "a random text",
"var2": "another random text",
"var3": "a third random text"
}
이는 값에 포함된 개행 문자에 대처할 수 없습니다. 그러나 다른 특수 문자는 .json에 의해 자동으로 인코딩됩니다 jo
.
답변2
를 사용하고 zsh
파일 구문이 의 구문과 호환되고 zsh
파일이 셸 확장자(예 var1=~/foo
: , var2=$var1
, , var3=$(uname)
...)를 사용하지 않고 값이 UTF-8로 인코딩된 텍스트라고 가정하면 다음과 같이 할 수 있습니다. :
tokens=( ${(Q)${(zZ[nC])"$(<file)"}} )
쉘 구문에 따라 파일의 내용을 표시하고( z
매개변수 확장 플래그를 사용하여 따옴표가 없는 개행을 공백으로 처리하고 쉘 주석을 제거 Z[flags]
하도록 조정(사용) ) 매개변수 확장 플래그를 사용하여 인용의 한 레이어를 제거합니다.n
C
Q
"
그런 다음 이러한 토큰을 json을 인코딩할 수 있는 항목(줄 바꿈, 백슬래시, 문자 등을 포함한 제어 문자 처리)에 전달할 수 있습니다 .
perl -CA -MJSON -le '
for (@ARGV) {
if (/(.*?)=(.*)/s) {
$h{$1} = $2;
}
}
print encode_json \%h' -- $tokens
file
예를 들어 다음과 같은 메시지가 있습니다 .
var1='a random text' # comment
var2='another'\'' random text'
var3='a third random text'
name=$'St\u00e9phane Chazelas'
empty=
at=@
more=broken\
down"with 1 \\ backslash"
numstring=1.1
그것은 다음을 제공합니다:
{"numstring":"1.1","name":"Stéphane Chazelas","empty":"","more":"brokendownwith 1 \\ backslash","var1":"a random text","at":"@","var2":"another' random text","var3":"a third random text"}