Unique/No Duplicated values in Shell Array Linux - arrays

I need to make a new array or just delete from the actual array the duplicate elements,
#The NTP IPS are the following ones:
#10.30.10.0, 10.30.10.0, 10.30.20.0, 10.30.20.0, 10.30.20.0
#!/bin/bash
ips_networks=()
for ip in ${ips_for_ntp[#]};do
ips_networks+=${ip%.*}.0
done
So I'll get ips_networks with duplicate ips, but I need just one of each ip into another array or the same, I have try with awk, set -A (Is not working on my linux), cut but with no luck, is there anyway to make an unique value array?

ips="10.30.10.0, 10.30.10.0, 10.30.20.0, 10.30.20.0, 10.30.20.0"
unique_ips=`echo $ips | sed -e "s/\s\\+//g" | sed -e "s/,/\\n/g"| sort | uniq`
echo $unique_ips #10.30.10.0 10.30.20.0

Related

Strange behaviour with Bash, Arrays and empty spaces

Problem:
Writing a bash script, i'm trying to import a list of products that are inside a csv file into an array:
#!/bin/bash
PRODUCTS=(`csvprintf -f "/home/test/data/input.csv" -x | grep "col2" | sed 's/<col2>//g' | sed 's/<\/col2>//g' | sed -n '1!p' | sed '$ d' | sed 's/ //g'`)
echo ${PRODUCTS[#]}
In the interactive shell, the result/output looks perfect as following:
burger
special fries
juice - 300ml
When i use exactly the same commands in bash script, even debugging with bash -x script.sh, in the part of echo ${PRODUCTS[#]}, the result of array is all files names located at /home/test/data/ and:
burger
special
fries
juice
-
300ml
The array is taking directory list AND messed up newlines. This don't happen in interactive shell (single command line).
Anyone know how to fix that?
Looking at the docs for csvprintf, you're converting the csv into XML and then parsing it with regular expressions. This is generally a very bad idea.
You might want to install csvkit then you can do
csvcut -c prod input.csv | sed 1d
Or you could use a language that comes with a CSV parser module. For example, ruby
ruby -rcsv -e 'CSV.read("input.csv", :headers=>true).each {|row| puts row["prod"]}'
Whichever method you use, read the results into a bash array with this construct
mapfile -t products < <(command to extract the product data)
Then, to print the array elements:
for prod in "${products[#]}"; do echo "$prod"; done
# or
printf "%s\n" "${products[#]}"
The quotes around the array expansion are critical. If missing, you'll see one word per line.
Tip: don't use ALLCAPS variable names in the shell: leave those for the shell. One day you'll write PATH=something and then wonder why your script is broken.

Create Array of File paths with a loop and grep through them

I want to save each output filepath to a variable and then grep through them to find the timestamp. I want to lable each variable by adding the nodeId from the node list I am looping through. When I try this with the following code I get an error
output1_1: command not found
nodeList=('1_1' '1_6' '2_1' '2_6')
for i in "${nodeList[#]}"
do
output${i}=$CWD/output/abc${i}.txt
times${i}=$(grep -m 1 '\"path\":' $output${i}| sed 's/.*timestampUtc\"://g' | sed 's/,.*//g')
done
As #muru suggested, try
declare -A output times
nodeList=('1_1' '1_6' '2_1' '2_6')
for i in "${nodeList[#]}"; do
output[${i}]=${PWD}/output/abc${i}.txt
times[${i}]=$(grep -m 1 '\"path\":' ${output[${i}]} | sed 's/.*timestampUtc\"://g' | sed 's/,.*//g')
done
One way to set a variable whose name is derived from another variable is to use the -v option to 'printf'.
To get the value of a variable whose name is in another variable (e.g. varname) use ${!varname}.
See Creating a string variable name from the value of another string and How can I generate new variable names on the fly in a shell script?.
Using these a possible loop body is:
output_var=output${i}
times_var=times${i}
printf -v "$output_var" '%s' "$CWD/output/abc${i}.txt"
printf -v "$times_var" '%s' "$(grep -m 1 '\"path\":' "${!output_var}" | sed 's/.*timestampUtc\"://g' | sed 's/,.*//g')"
Note that (unless CWD is set elsewhere in your program) you probably want $PWD instead of $CWD.

using command variable in column output not working

I'm using a script that uses curl to obtain specific array values from a configuration. I'd like to place the output into columns separating values (values are unknown to script). Here's my code:
# get overlay networks and their details
get_overlay=`curl -H "X-Person-Token: $auth_token" -H "X-Person-Email: $auth_email" -k "$api_host/api/v1/networks"`
# array of overlay names with uuid
overlay_name=`echo $get_overlay | jq '.[] | .name'`
overlay_uuid=`echo $get_overlay | jq '.[] | .uuid'`
echo ""
echo -e "Overlay UUID\n$oname $ouuid" | column -t
exit 0
Here's the ouput:
Overlay UUID
"TESTOVERLAY"
"Auto_API_Overlay"
"ANOTHEROVERLAYTEST" "ea178905-6ab0-4154-ab05-412dc4b39151"
"e5be9dbe-b0fc-4e30-aaf5-ac4bdcd863a7"
"850ebf6b-3651-4cf1-aae1-5a6c03fad61b"
What I was expecting was:
Overlay UUID
"TESTOVERLAY" "ea178905-6ab0-4154-ab05-412dc4b39151"
"Auto_API_Overlay" "e5be9dbe-b0fc-4e30-aaf5-ac4bdcd863a7"
"ANOTHEROVERLAYTEST" "850ebf6b-3651-4cf1-aae1-5a6c03fad61b"
I'm an absolute beginner at this, any insight is very much appreciated.
Thanks!
I would suggest using paste to combine your two variables line by line:
paste <(printf 'Overlay\n%s\n' "$name") <(printf 'UUID\n%s\n' "$uuid") | column -t
Two process substitutions are used to pass the contents of each variable along with their titles.

Having issues using IFS to cut a string into an array. BASH

I have tried everything I can think of to cut this into separate elements for my array but I am struggling..
Here is what I am trying to do..
(This command just rips out the IP addresses on the first element returned )
$ IFS=$"\n"
$ aaa=( $(netstat -nr | grep -v '^0.0.0.0' | grep -v 'eth' | grep "UGH" | sed 's/ .*//') )
$ echo "${#aaa[#]}"
1
$ echo "${aaa[0]}"
4.4.4.4
5.5.5.5
This shows more than one value when I am looking for the array to separate 4.4.4.4 into ${aaa[0]} and 5.5.5.5 into ${aaa[1]}
I have tried:
IFS="\n"
IFS=$"\n"
IFS=" "
Very confused as I have been working with arrays a lot recently and have never ran into this particular issue.
Can someone tell me what I am doing wrong?
There is a very good example on how to use IFS + read -a to split a string into an array on this other stackoverflow page
How does splitting string to array by 'read' with IFS word separator in bash generated extra space element?
netstat is deprecated, replaced by ss, so I'm not sure how to reproduce your exact problem

(bash) How to access chunks of command output as discrete array elements?

nmcli -t -f STATE,WIFI,WWAN
gives the output
connected:enabled:disabled
which I'd like to convert to something like
Networking: connected, Wifi: enabled, WWAN: disabled
The logical solution to me is to turn this into an array. Being quite new to bash scripting, I have read that arrays are just regular variables and the elements are separated by whitespace. Currently my code is
declare -a NMOUT=$(nmcli -t -f STATE,WIFI,WWAN nm | tr ":" "\n")
which seems to sort of work for a for loop, but not if i want to ask for a specific element, as in ${NMOUT[]}. Clearly I am missing out on some key concept here. How do I access specific elements in this array?
IFS=: read -a NMOUT < <(nmcli -t -f STATE,WIFI,WWAN)
Ignacio Vazquez-Abrams provided a much better solution for creating the array. I will address the posted question.
Array's in bash are indexed by integers starting at 0.
"${NMOUT[0]}" # first element of the array
"${NMOUT[2]}" # third element of the array
"${NMOUT[#]}" # All array elements
"${NMOUT[*]}" # All array elements as a string
The following provides good information on using arrays in bash: http://mywiki.wooledge.org/BashFAQ/005

Resources