명령줄을 사용하여 여러 변수를 나열하는 파일을 JSON으로 직접 변환할 수 있나요?

명령줄을 사용하여 여러 변수를 나열하는 파일을 JSON으로 직접 변환할 수 있나요?

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) )'

이는 joJSON 문서를 생성하는 데 처음 사용됩니다.

{
   "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]하도록 조정(사용) ) 매개변수 확장 플래그를 사용하여 인용의 한 레이어를 제거합니다.nCQ

"그런 다음 이러한 토큰을 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"}

관련 정보