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

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

file다음과 같은 내용의 a가 있다고 가정해 보겠습니다 .

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으로 직접 변환할 수 있나요?


여기서 내 대안 솔루션은 이 파일 내에서 char 단위로 이동하는 코드(셸을 사용하지 않음)를 개발한 다음 루프에서 모든 것을 동적으로 분리하는 것입니다. 하지만 이 질문을 하는 이유는 솔루션이 지나치게 복잡해지는 것을 방지하고 싶기 때문입니다.

답변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"
}

이는 값에 포함된 개행 문자에 대처할 수 없습니다. 그러나 다른 특수 문자는 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"}

관련 정보