- Create a Json using bash script
- 2 Answers 2
- Answer
- UPDATE
- Answer 1:
- Alternative answer
- Explanation
- Info regarding jq
- How to Create JSON File?
- 1. Using Text Editor
- 2. Using Online Tool
- 3. Create a file from the JSON URL
- 3.1 Create JSON file in Linux
- Know More about JSON :
- Related Links:
- How to write json file using bash in Linux?
- Method 1: Using the echo Command
- Method 2: Using the printf Command
- Method 3: Using a Third-Party Utility, such as jq
Create a Json using bash script
Before we can proceed, we of course need to see what the formatting of the file containing CIDRs looks like. Once we know how the inividual properties are listed (i.e. are the key-value pairs written on a single line for each CIDR , or is does the formatting use tab-delimited multi-line syntax etc. ) conversion to JSON should be fairly straightforward.
2 Answers 2
There are two main issues in your data and code:
- You have an input file in DOS or Windows text file format.
- Your code creates multiple single-element arrays rather than a single array with multiple elements.
Your input file, lol , appears to be a text file in DOS/Windows format. This means that when a utility that expects a Unix text file as input reads the file, each line will have an additional carriage-return character ( \r ) at the end.
You should convert the file to Unix text file format. This can be done with e.g. dos2unix .
As for your code, you can avoid the shell loop and let jq read the whole file in one go. This allows you to create a single result array rather than a set of arrays, each with a single object, which your code does.
The following assumes that the only thing that varies between the elements of the top-level array in the result is the source value (there is nothing in the question that explains how the max and min values of the source and destination ports should be picked):
jq -n -R ' [inputs] | map( < source: ., protocol: "17", isStateless: true, udpOptions: < sourcePortRange: < min: 521, max: 65535 >, destinationPortRange: < min: 1, max: 65535 >> > )' cidr.txt
or in the same compact one-line form as in your question:
jq -n -R '[inputs]|map(,destinationPortRange:>>)' cidr.txt
Using inputs , jq reads the remaining inputs. Together with -R , it will read each line of cidr.txt as a single string. Putting this in an array with [inputs] we create an array of strings. The map() call takes each string from this array and transforms it into the source value for a larger, otherwise static object.
Add -c to the invocation of jq to get «compact» output.
If you don’t want to, or are unable to, convert the input data from DOS to Unix text form, you can remove the carriage-return characters from within the jq expression instead.
To do this, replace the . after source: with (.|rtrimstr(«\r»)) , including the outer parentheses. This trims the carriage-return from the end of each string read from the file.
Answer
This should get you the exact syntax you require:
In the example , the file containing your CIDR values is named cidr.txt and appears to contain only IP addresses along with subnets, i.e. other parameters remain constant. If you actually need to change these additional parameters (i.e. the port ranges you provided are not actually the same for all cidr then I will update my answer, and provide a fully fleshed out template)
Additionally, you will require ‘jq’ , which is the ubiquitous application for dealing with JSON through bash. It may likely already be installed these days, but if not then sudo apt install jq per usual.
while read cidr ; do jq -n --arg CIDR "$cidr" ',"sourcePortRange": >>' done < cidr.txt | jq --slurp
Using the four-line file sample you provided, the output of the above will give you the following in the terminal:
[ < "source": "1.1.1.0/22", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 65535, "min": 1 >, "sourcePortRange": < "min": 521, "max": 65535 >> >, < "source": "2.2.2.0/24", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 65535, "min": 1 >, "sourcePortRange": < "min": 521, "max": 65535 >> >, < "source": "5.5.5.0/21", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 65535, "min": 1 >, "sourcePortRange": < "min": 521, "max": 65535 >> >, < "source": "6.6.0.0/16", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 65535, "min": 1 >, "sourcePortRange": < "min": 521, "max": 65535 >> > ]
UPDATE
In order to fix the above output, you need to "repair" the line termination of your CIDR file. There are two ways of doing so:
Answer 1:
You can make the following changes to your script
#!/bin/bash # There are four changes made to the script: # 1. The addition of `tr` in order to eliminate '\r'. # 2. Removal of '[' and ']' inside the `jq` command. # 3. Addition of `jq --slurp` to enforce your specified JSON format. # 4. Addition of double-quotes around `$lel` to prevent splitting. lel=$(while read cidr ; do cidr=$(echo "$cidr" | tr -d '\r' ); jq -n --arg CIDR "$cidr" ',"sourcePortRange": >>' done < lol | jq --slurp ) echo "$lel"
Alternative answer
You can "repair" the file containing our list of CIDRs:
cp lol lol_old cat lol_old | tr -d '\r' > lol
Then, you can use the earlier version of your script, albeit with the corrections explained in #2-4 comments of the script included above.
Explanation
The reason for the \r found in your output is actually found in the formatting of your particular file containing your CIDRs, which happens to follow Windows - and not Unix - line termination standard.
The \r symbol you see in your output is actually present in your source file as well, where it is used along with \n to terminate each individual line. Both \r and \n are invisible characters. The combination of \r\n is known as CRLF - carriage return + line feed - which is a remnant from the age of typewriters, yet for some reason is still used by Windows systems. On the other hand, Unix uses only LF to terminate lines, where it is represented by \n in its escaped form.
To confirm this peciular behavior, you can try executing the following:
head -n 1 lol | xxd -ps 312e312e312e302f32320d0a
In the above output - the first line of your file converted to its hex form - ends with 0d0a . This HEX combination represent CR+LF. On the other hand, if you execute the following directly inside of your Bash terminal:
echo "abcd" | xxd -ps 616263640a
you will find that the output follows Unix standard, where the line termination uses simple 0a , i.e. the hex representation of LF.
Note: This line-termination issue is incredibly common, widespread and something one always needs to be on the lookout for operating from inside Unix on files that may have been generated under Windows.
Info regarding jq
The above example (the while read loop) sends its output to the terminal, but you can of course use redirection if you need to store it in a file, using the standard syntax:
while read cidr; do [. ] ; done < cidr.txt >outcidr.json
This file will contain the pretty-printed JSON output, but if you need/prefer your output to be contstrained to a single line, you can do:
cat outcidr.json | tr -d '\n' | tr -s ' '
More importantly, if you ever in the future end up with a single-line, complex JSON output that looks impossible to decipher, jq can be used to reformat and pretty-print it`:
echo '[,"sourcePortRange":>>,,"sourcePortRange":>>,,"sourcePortRange":>>]' > bad_output.json cat bad_output.json | tr -d '\r' | jq '' [ < "source": "1.1.1.0/24", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 55555, "min": 10001 >, "sourcePortRange": < "min": 521, "max": 65535 >> >, < "source": "2.2.2.0/24", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 55555, "min": 10001 >, "sourcePortRange": < "min": 521, "max": 65535 >> >, < "source": "3.3.3.0/24", "protocol": "17", "isStateless": true, "udpOptions": < "destinationPortRange": < "max": 55555, "min": 10001 >, "sourcePortRange": < "min": 521, "max": 65535 >> > ]
# Getting first-order keys for each of the 3 objects jq '.[] | keys' bad_output.json [ "isStateless", "protocol", "source", "udpOptions" ] [ "isStateless", "protocol", "source", "udpOptions" ] [ "isStateless", "protocol", "source", "udpOptions" ]
# Getting values corresponding to the selected key" jq '.[] | .source ' outcidr.txt "1.1.1.0/22" "2.2.2.0/24" "5.5.5.0/21" "6.6.0.0/16"
How to Create JSON File?
Once we understand JSON, there are three ways to create a new JSON.
- Using Text Editor
- Using Online Tools such as https://jsonformatter.org
- Create a file from the JSON URL
1. Using Text Editor
Open a Text editor like Notepad, Visual Studio Code, Sublime, or your favorite one.
Copy and Paste below JSON data in Text Editor or create or use your JSON based on the What is JSON article.
1 2 3 4 5 6 7 8 9 10 11 12
"InsuranceCompanies": "Top Insurance Companies": [ "No": "1", "Name": "Berkshire Hathaway", "Market Capitalization": "$661 B" > ], "Time": "Dec 2022" > >
Use this JSON validator tool to validate the JSON
Once file data are validated, save the file with the extension of .json, and now you know how to create a Valid JSON document.
2. Using Online Tool
Open a JSON Formatter tool from the link below
Copy and Paste the JSON Data, which is mentioned in Option 1 in the Input tool of the online tool
Download this file using the download icon mentioned in the Right input area. It will download the JSON file.
This jsonformatter.org already supports the JSON validation. It will create a New JSON file and will allow downloading.
Now, if you already have a JSON document or file, you can upload it to this tool, modify or delete a few objects, an array of the JSON, and download the updated and valid JSON file.
This tool also helps to create a JSON from a text file. Upload text files using the upload file button, and JSON will be automatically validated and beautified.
3. Create a file from the JSON URL
The developer needs to work with API; nowadays, 95% of API returns data as JSON.
Here are a few samples of the JSON URL. Now click on these JSON samples.
Once these links are open, “save as” the browser’s functionality and save these links as files. It will generate a JSON file and save it on your device.
I hope this article helps you to understand basic ways to make or create valid JSON files and beautify them.
3.1 Create JSON file in Linux
Use the jq command to create a JSON file in Linux. This command will build a JSON file in the current directory.
jq -n --arg greeting GoodMorning '' > sample.json
the jq is a lightweight and flexible command-line JSON processor. Install the jq in ubuntu using the sudo apt-get install jq
Know More about JSON :
Related Links:
How to write json file using bash in Linux?
In the world of software development, JSON is a common data interchange format used in RESTful APIs. If you are working in a Linux environment and need to write a JSON file, there are several ways to accomplish this using Bash scripts. Whether you need to create a new file or update an existing one, here are a few methods to consider:
Method 1: Using the echo Command
Here is a step-by-step guide on how to write a JSON file using Bash with the "echo" command:
- Open your terminal and navigate to the directory where you want to create the JSON file.
- Create a new file with the ".json" extension. You can use the touch command to create an empty file.
This will write the JSON data '' to the example.json file.
- If you want to add more data to the JSON file, you can use the ">>" operator to append to the file instead of overwriting it.
echo '' > example.json echo '' >> example.json
This will write the JSON data '' to the example.json file and then append the JSON data '' to the end of the file.
- You can also use variables to store the JSON data and then write it to the file using the echo command.
data='' echo $data > example.json
This will store the JSON data '' in the "data" variable and then write it to the example.json file.
That's it! You now know how to write a JSON file using Bash with the "echo" command.
Method 2: Using the printf Command
To write a JSON file using Bash, you can use the printf command. Here are the steps:
- Use the printf command to write the JSON data to a file. You can use the > symbol to redirect the output to a file. For example:
This will write the JSON data to a file named data.json .
printf '%s\n' "$json" | jq '.' > data.json
This will write the pretty-printed JSON data to the same file.
Here is the complete Bash script:
#!/bin/bash json='' printf '%s\n' "$json" > data.json printf '%s\n' "$json" | jq '.' > pretty.json
This script will write the JSON data to data.json and the pretty-printed JSON data to pretty.json .
That's it! This is how you can write a JSON file using Bash and the printf command.
Method 3: Using a Third-Party Utility, such as jq
To write a JSON file using Bash on Linux, you can use a third-party utility such as jq. Here's how you can do it step by step:
- First, you need to install jq. You can use the package manager of your Linux distribution to install it. For example, on Ubuntu, you can use the following command:
#!/bin/bash data='' echo $data | jq '.' > data.json
In this example, we define a JSON data object and use the jq command to format it and write it to a file named data.json .
#!/bin/bash name="John Doe" age=30 city="New York" jq -n --arg name "$name" --arg age "$age" --arg city "$city" '' > data.json
In this example, we define three Bash variables and use the jq command to format them as a JSON object and write it to a file named data.json .
#!/bin/bash fruits=("apple" "banana" "cherry") jq -n --argjson fruits "$(echo $ | jq -R . | jq -s .)" '' > data.json
In this example, we define a Bash array and use the jq command to format it as a JSON array and write it to a file named data.json .
That's it! With these examples, you can write a JSON file using Bash on Linux using the third-party utility jq.