Kann ich eine Datei, die mehrere Variablen auflistet, mithilfe der Befehlszeile direkt in JSON konvertieren?

Kann ich eine Datei, die mehrere Variablen auflistet, mithilfe der Befehlszeile direkt in JSON konvertieren?

Nehmen wir an, ich habe eine filemit folgendem Inhalt:

var1='a random text'
var2='another random text'
var3='a third random text'

evalIch weiß, dass ich alle diese Variablen direkt in meiner Shell speichere, wenn ich den folgenden Befehl verwende :

$ eval $(cat file)

Wenn ich das mache, erstellt meine Shell $var1und $var2mit $var3den entsprechenden Inhalten. Mit diesem Wissen könnte ich manuell ein JSON wie das folgende generieren:

$ JSON="{ \"var1\" : \"$var1\", \"var2\" : \"$var2\", \"var3\" : \"$var3\"}"

Und das Ergebnis wäre ein gültiges JSON:

$ echo $JSON
{ "var1" : "a random text", "var2" : "another random text", "var3" : "a third random text"}

Das Problem hier ist, dass ich die Schlüssel var1, var2 und var3 fest codiere. In meinem Fall könnte die Datei größer sein und mehr Variablen enthalten (nicht nur var1, var2 und var3). Ich habe mich gefragt, ob es eine einfache Möglichkeit gibt, dies über die Befehlszeile zu erreichen, genau wie evalbeim Speichern von Dateivariablen in der Shell, aber anstatt die Variablen zu speichern, wird eine JSON-Ausgabe generiert. Ist das möglich? Kann ich eine so strukturierte Datei über die Befehlszeile direkt in JSON konvertieren?


Meine alternative Lösung wäre, einen Code zu entwickeln (ohne Shell), der diese Datei Zeichen für Zeichen durchgeht und dann alles dynamisch in einer Schleife trennt. Aber ich stelle diese Frage, weil ich eine übermäßige Komplizierung der Lösung vermeiden möchte.

Antwort1

Durch die Verwendung einer Kombination joausHier) und jqvonHier), ohne Shell-Variablen zu erstellen oder die Shell die Datei überhaupt interpretieren zu lassen:

jo <file |
jq --arg sq "'" '.[] |= ( ltrimstr($sq) | rtrimstr($sq) )'

Damit wird zunächst jodas JSON-Dokument erstellt

{
   "var1": "'a random text'",
   "var2": "'another random text'",
   "var3": "'a third random text'"
}

(aber in einer einzigen Zeile). Dies geschieht, indem die Variablenzuweisungen in Ihrer Datei als Schlüssel-Wert-Paare interpretiert werden.

Anschließend werden mit dem jqTool die einfachen Anführungszeichen am Anfang und Ende jedes Werts gelöscht.

Das Endergebnis ist

{
  "var1": "a random text",
  "var2": "another random text",
  "var3": "a third random text"
}

Dies kann nicht mit in die Werte eingebetteten Zeilenumbrüchen umgehen. Andere Sonderzeichen werden jedoch automatisch von JSON-codiert jo.

Antwort2

Mit zshund unter der Annahme, dass die Syntax der Datei mit der von kompatibel ist , dass die Datei keine Shell-Erweiterungsfunktionen (wie , , ...) zshverwendet und dass die Werte in UTF-8 codierter Text sind, könnten Sie Folgendes tun:var1=~/foovar2=$var1var3=$(uname)

tokens=( ${(Q)${(zZ[nC])"$(<file)"}} )

Um den Inhalt dieser Datei gemäß der Shell-Syntax zu tokenisieren (mithilfe des zParametererweiterungsflags, optimiert (mit Z[flags]), um nnicht in Anführungszeichen gesetzte Zeilenumbrüche als Leerzeichen zu betrachten und CShell-Kommentare zu entfernen) und um eine Anführungszeichenebene mit dem QParametererweiterungsflag zu entfernen.

Anschließend können Sie diese Token an etwas übergeben, das JSON kodieren kann (achten Sie auf Steuerzeichen, einschließlich Zeilenumbruch, Backslash, "Sonderzeichen usw.):

perl -CA -MJSON -le '
  for (@ARGV) {
    if (/(.*?)=(.*)/s) {
      $h{$1} = $2;
    }
  }
  print encode_json \%h' -- $tokens

Zum Beispiel eine filewie:

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

Es gibt:

{"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"}

verwandte Informationen