store value of cat to a variable in unix - arrays

I need to assign two columns (column 2 and 6) in a text file to a variable as an array. so that i can call them back element by element.
the code below puts the whole column as one string element in k and l.
and the echo command will not return anything as everything is stored in the first element
k=`(cat mydata.txt | awk '{print $2}')`
l=`(cat mydata.txt | awk '{print $6}')`
echo ${k[2]}
echo ${l[2]}
below is an example of data set i used.
60594412 56137844 48552535 44214019 44121294 28652826 21975449 21718959 18208824 18004925 13299946 12969796 11990006 10435260 9992615 9975420 9223972 8918246 8730367 7723045 7316105 6772270 6301570 5662296 4653831 3769516 3343899 2639162 2393169 1992206 1838674 1681498 1563810 1389679 1267762 1253490 1205487 940968 718249 702722 655069 649121 619911 437735 284727 264334 252627 233213 185924 177421 160412 156581 143128 107247 87194 81369 74594 74185

Swap the order of the parentheses and backticks.
k=(`cat mydata.txt | awk '{print $2}'`)
l=(`cat mydata.txt | awk '{print $6}'`)
Stylewise, you could get rid of the useless use of cat and also change the backticks to $(...), which is generally preferable.
k=( $(awk '{print $2}' mydata.txt) )
l=( $(awk '{print $6}' mydata.txt) )

Related

Shell Remove lower versions from array

I have the following array:
ARRAYNAME=(value_1.21.zip value_1.22.zip valueN_0.51.zip valueN_0.52.zip valueM_3.52)
I want to remove the lower versions of the same element and to have the following array:
ARRAYNAME=(value_1.22.zip valueN_0.52.zip valueM_3.52)
In this moment I am using this approach to remove the same elements
ARRAYNAMESORT=$(tr ' ' '\n' <<< "${ARRAYNAME[#]}" | sort -u | tr '\n' ' ')
but I am stuck in removing the lower versions. Does anyone has an idea how to achieve this?
Based on the text structure [Name]_[version].zip
ARRAYNAME=($(printf '%s\n' "${ARRAYNAME[#]}" | awk '{print $1,$1}' | cut -d'_' -f2- | sort -n | sed 1d | awk '{print $2}' | paste -s))
Explanation:
print all array elements printf '%s\n' "${ARRAYNAME[#]}"
duplicate the name in two column awk '{print $1,$1}'
remove left text from the first column cut -d'_' -f2-
sort then remove smallest one which is in the first line sort -n | sed 1d
get the second column the make it serial awk '{print $2}' | paste -s

Building array from awk output

Can anyone explain why the following doesn't work please?
list
the letter is d
the number is 4
the number is 2
the letter is g
script.sh
#!/bin/bash
cat "$1" | grep letter | array=($(awk '{print $4}'))
for i in "${array[#]}"
do
:
echo $i
done
If I run this bash script.sh list I expect the array to print d and g, but it doesn't. I think its because of how I am trying to set the array.
I think its because of how I am trying to set the array.
Each command in a pipeline | is run in a subshell - as a separate process. The parent process does not "see" variable changes from a child process.
Just:
array=($(grep letter "$1" | awk '{print $4}'))
or
array=($(awk '/letter/{print $4}' "$1"))
Run variable assignment in the parent shell.
You should assign the complete row of piped commands to a variable.
array=($(cat "$1" | grep letter | awk '{print $4}'))
The cat and grep command can be combined with awk, but why do you want an array?
I think you want the process each element in one loop, so first remove the double quotes:
for i in ${array[#]}
do
:
echo $i
done
Next, try to do this without an array
while read -r i; do
:
echo $i
done < <(awk '/letter/ {print $4}' "$1")

Spaces in array content getting broken with grep

I am using array to tackle with spaces in line of my file. But when i am using grep to filter with value of array it is breaking because of spaces.
For example my line is as per below
bbbh.cone.abc.com:/home 'bbbh.cone.abc.com
As it has spaces i am using array as per below.
object1=$(echo "$line" | awk '{print $1}' )
object2=$(echo "$line" | awk '{print $2}' )
object3=$(echo "$line" | awk '{print $3}' )
object4=$(echo "$line" | awk '{print $4}' )
hiteshcharry=("$object1" "$object2" "$object3" "$object4")
grep "${hiteshcharry[#]}" <filename>
It give me error because of spaces.
Below is the example.
I have below line in my file.
st.cone.abc.com:/platform/sun4v/lib/sparcv9/libc_psr.so.1 space 'st.cone.abc.com space [/platform/sun4v/lib/sparcv9/libc_psr.so.1]'
So i have 2 spaces in my above line. I have written my script in such way so that it can handle a line with maximum 4 spaces.
When i am running below command
omnidb -session "$sessionid" -detail | grep "${hiteshcharry[#]}"
it give me error because of spaces. However when i print the value of array it show me correct value.
Example : -
one of line from my file is as below( it has 2 spaces)
st.cone.abc.com:/platform/sun4v/lib/sparcv9/libc_psr.so.1 space 'st.cone.abc.com space [/platform/sun4v/lib/sparcv9/libc_psr.so.1]'
I am putting this value in my array named as hiteshcharry. when i am running below command
omnidb -session "$sessionid" -detail | grep "${hiteshcharry[#]}"
It is giving me error because of spaces in value of array. In output it should filter the line having value equal to array named hiteshcharry.
I hope this is clear now.
Output of omnidb command is in picture. So i want to grep the lines having
"st.cone.abc.com:/platform/sun4v/lib/sparcv9/libc_psr.so.1 space
'st.cone.abc.com space [/platform/sun4v/lib/sparcv9/libc_psr.so.1]'" from
output of omnidb command which is in picture
enter image description here
Thanks. i have added declare -p hiteshcharry and it start printing the each elements of array. But i am error shown in picture .
enter image description here
When you pass your array to grep through "${array[#]}", grep will see each array element as a separate argument. So, the first element would become the pattern to search for, and the second element onwards would become the file names to be searched on. Obviously, that's not what you want.
You can use process substitution to make grep match the strings contained in your array, like this:
omnidb -session "$sessionid" -detail | grep -Fxf <(printf '%s\n' "${hiteshcharry[#]}")
printf will print your array elements one line per element
grep -Fxf treats the about output as a file containing strings to be searched (-F option treats them as strings, not patterns, -x matches the whole line of omnidb output, preventing any partial matches)

BASH scipt. how to code if (array=nothing) then echo "no element in array" in bash script

in bash script, I define a array:
array=$(awk '{print $4}' /var/log/httpd/sample | uniq -c | cut -d[ -f1)
Now, I want to translate this content to code in bash script:
"if there is NOT any element in array, it means array=nothing, then echo "nothing in array".
help me to do that??? Thanks a lot
*besides, I want to delete access_log's content periodically every 5min (/var/log/httpd/access_log). Please tell me how to do that??*
Saying:
array=$(awk '{print $4}' /var/log/httpd/sample | uniq -c | cut -d[ -f1)
does not define an array. This simply puts the result of the command into the variable array.
If you wanted to define an array, you'd say:
array=( $(awk '{print $4}' /var/log/httpd/sample | uniq -c | cut -d[ -f1) )
You can get the count of the elements in the array by saying echo "${#foo[#]}".
For checking whether the array contains an element or not, you can say:
(( "${#array[#]}" )) || echo "Nothing in array"

Failure to populate Bash array from AWK statement

I need to get 1 or more locations from a config file and then check each location for some files. I have an AWK and SED combination which finds the locations and then read the list of files from a text file. I want to check each location for the file and thought to use a bash array to hold the locations.
However for some reason I cannot populate the array from the AWK statement. It appears to me that it loads the complete content into the first element.
If I manually populate the array it works; e.g. replace the line array=$(awk ...
with
array[1]=/docs01/objdata/admin/p1dig
array[2]=/docs02/objdata/admin/p1dig
array[3]=/docs03/objdata/admin/p1dig
array[4]=/docs04/objdata/admin/p1dig
In the code snippet below I have removed the outer (filename) loop and added some debugging context.
#!/bin/bash
declare -a array
OBJECTIVE_CONF=/u01/app/objective/perf/DOS1/config/objConf.xml
FILE=/tmp/DoS1_files.dsv
# IFS=$"/n"
array=$(awk '/<volume>/,/<\/volume>/' $OBJECTIVE_CONF | grep "<path>" | sed "s#<[/]*path>##g" | sed 's/^[ \t]*//' |sed 's/[ \t]*$//' )
element_count=${#array[#]}
echo "element_count is : $element_count "
echo "index is: $index"
echo "${array[$index]}"
echo "filename loop"
index=0
while [ "$index" -lt "$element_count" ]
do
let "index = $index + 1"
echo "index is: $index"
echo "ls ${array[$index]}/filename_from_loop"
done
echo "leaving loop"
The Awk statement gives me the expected result when run from the command line. I AWK for the start and finish XML tags, grep inside that for the PATH and use SED to remove the PATH exm tags and leading and training space.
bash-3.00$ awk '/<volume>/,/<\/volume>/' $OBJECTIVE_CONF | grep "<path>" | sed "s#<[/]*path>##g" | sed 's/^[ \t]*//' |sed 's/[ \t]*$//'
/docs01/objdata/admin/p1dig
/docs02/objdata/admin/p1dig
/docs03/objdata/admin/p1dig
/docs04/objdata/admin/p1dig
$(<command>) substitution does not produce an array. To get an array, use another pair of parentheses:
array=($(<command>))
You can use the readarray statement too :
readarray array < <(command)
the differences than just assign, like array=($(<command>)), is that you have more control on the final array, (man)
the < <(command) is for function/command expansion without a child process.

Resources