Reputation: 161
how to write a bash for loop to create a template
Source File:
"INTEL SSDPEL1D380GA CCCCCCCCCCCCCCC 01",
"Samsung SSD 970 PRO 1TB XXXXXXXXXXXXXXX 01",
"Samsung SSD 970 PRO 1TB YYYYYYYYYYYYYYY 01",
"Samsung SSD 970 PRO 1TB ZZZZZZZZZZZZZZZ 01",
"Samsung SSD 970 PRO 1TB IIIIIIIIIIIIIII 01"
Desired Output:
node_nvme_device{manufacturer="INTEL",partnumber="SSDPEL1D380GA",serialnumber="CCCCCCCCCCCCCCC"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="XXXXXXXXXXXXXXX"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="YYYYYYYYYYYYYYY"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="ZZZZZZZZZZZZZZZ"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="IIIIIIIIIIIIIII"} 1
My attempted and failed code
awk 'NF>1 {
"node_nvme_device{manufacturer="$1",partnumber="$2",serialnumber="$3"} 1" }' source_file
Upvotes: 1
Views: 918
Reputation: 785581
Here is another awk alternative:
awk '
{
mf = $1
sn = $(NF-1)
gsub(/^[[:blank:]]*"[^[:blank:]]+[[:blank:]]+|[[:blank:]]{2,}[[:alnum:]].*$/, "")
printf "node_nvme_device{manufacturer=%s\",partnumber=\"%s\",serialnumber=\"%s\"} 1\n", mf, $0, sn
}' file
node_nvme_device{manufacturer="INTEL",partnumber="SSDPEL1D380GA",serialnumber="CCCCCCCCCCCCCCC"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="XXXXXXXXXXXXXXX"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="YYYYYYYYYYYYYYY"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="ZZZZZZZZZZZZZZZ"} 1
node_nvme_device{manufacturer="Samsung",partnumber="SSD 970 PRO 1TB",serialnumber="IIIIIIIIIIIIIII"} 1
Upvotes: 2
Reputation: 23864
It is possible to use a one-liner e.g. Perl but using a shell script you will have more / better flexibility, scalability, maintenance of your code for later use cases.
The proper solution will be in two major steps:
So for part 1 you can use mapfile
built-in bash command to read all the lines of the file you have into an array.
#!/bin/bash
mapfile -t arr < file.txt
Now you will have an array of each line e.g. echo ${arr[0]}
will print your first line and echo ${arr[@]}
will print all lines. Then you can read each line (step 2) into an other array and use them:
#!/bin/bash
# read all lines
mapfile -t arr < file.txt
# read just line 1
mapfile -t line1 < <(echo ${arr[0]} | tr ' ' '\n')
# print first element of line 1
echo ${line1[0]}
# output
"INTEL
then you can refactor these two steps to your own specific one.
Please notice you do not have to use the second mapfile
(step 2) manually and you can use a for-loop
for reading first array (array of lines) e.g.
for line in ${arr[@]}; do
# read each line into an new array
mapfile -t each_line < <(echo ${line[@]} | tr ' ' '\n');
# do whatever you need to do with each line
echo "each line: ${each_line[@]}";
done
Plus you should get rid of extra characters in the file e.g. "
, ,
, etc. before using the contents / values.
Upvotes: 3
Reputation: 12887
Assuming that the data is tab delimited and using Python:
#!/usr/bin/python
for f in open("parts"): # Open a file called parts
f=f.replace("\"","") # Remove quotes from the line
f=f.replace(",","") # Remove commas from the line
bits=f.split("\t") # Split the line into the array bits based on tabs
bits1=bits[0].split(" ") # Split the first index further into bits1 this time using " "
stryng=bits1[0]
numb=int(bits[2])
for i in range(1,len(bits1),1): # Loop through bit1, building a strinf stryng
stryng=stryng + " " + bits1[i]
print("node_nvme_device{manufacturer=\"" + bits1[0] + "\",partnumber=\"" + stryng + "\",serialnumber=\"" + bits[1] + "\"} " + str(numb)) # Print the data in format required
Upvotes: 0
Reputation: 133630
With your shown samples only, could you please try following.
awk '
match($0,/".* /){
val1=""
val=substr($0,RSTART+1,RLENGTH-1)
sub(/[[:space:]]+$/,"",val)
num=split(val,arr," ")
for(i=2;i<=num;i++){
val1=(val1?val1 OFS:"")arr[i]
}
printf("node_nvme_device{manufacturer=\"%s\",partnumber=\"%s\",serialnumber=\"%s\"} %01d\n",arr[1],val1,$(NF-1),$NF)
}' Input_file
Explanation: Simply using match function of awk
to match from starting to till bigger space as per shown samples, then saving its matched sub string into val, removing spaces to get rid of it, then creating val2 which has al values from 2nd element to till end of array here(since there are multiple values in samples by OP eg--> SSD 970 PRO 1TB
to match here), then finally printing the values as per needed output using printf, simply passing values(fields of current line and array's element with val1 value here).
Upvotes: 3