Using awk to parse a string from a file - arrays

I'm still learning Unix and I'm having issues understanding the following line of code.
echo "$lines" | awk '{split($0,a,":"); print a[3],a[2],a[1]}'
I don't understand what is happening with the array a in the line of code above. Is it declaring the array and setting it equal to the string it's parsing? If it is declaring the array a, then, why can't I print out the results later on in the code?
echo "${a[1]}"
The line above prints an empty line and not what has been stored in the array a when the string was parsed. I know there is always something in the string that needs to be parsed and when I call the array a[1] I know that I'm in inside the scope. I just don't see/understand what is happening with the array a that prevents me from printing it out later on in the code.

Your code is printing a line for each line of input. If you dont have get output, my first guess would be, that you don't have input.
Given an input of:
lines="ab:cd:ef
ij:kl:m"
the output is:
ef cd ab
m kl ij
awk is executing the commands (which is everything in between the single quotes) for each line of input. First splitting the input line $0 at each : into an array a, then printing the first three elements in reverse order.
If you try to access an array element in the shell, what echo suggests, then you are too late. The array exists within awk and is gone when awk has finished.

Related

How to modify a string of values in bash?

I have an array of strings. These strings contain values in the format of an (x,y) coordinate pair, e.g. string one contains "42,37", string two contains "54,17", and so forth. How can I modify this array of strings such that "42,37" becomes "+42+37", "54,17" becomes "+54+17", and so on?
I'm rather new to bash and writing a simple utility, I've racked my brain over this issue for the past day.
With bash, after the for loop new_array will contain your desired format.
a=("42,37" "54,17")
x=0
for i in "${a[#]}"; do
b=${a[$x]}
new_array[$x]="+${b:0:2}+${b:3:2}"
((x++))
done
Output:
for i in "${new_array[#]}"; do echo $i; done
+42+37
+54+17

Can't fill bash array

I'm running Ubuntu 14.04 and am trying to fill an array in a shell script so that I can loop over it and utilize its contents to fill a text file. However, there's a snag: it doesn't seem to be filling.
I've simplified the larger script that I'm working with down to the essential issue, reprinted below:
WL_START=1
WL_END=5
WL_INC=1
wl_range=$(seq $WL_START $WL_INC $WL_END)
declare -a WL
for i in $wl_range # loop through sequence and fill array
do
WL[$i]=${wl_range[$i]}
done
echo $wl_range
echo ${wl_range[1]}
echo $WL
echo ${WL[1]}
However, my output looks like this:
1 2 3 4 5
empty line
empty line
empty line
Any ideas? I know that people say to just use seq to fill the array, but I had the same problem there as well.
Too much work.
WL=($(seq $WL_START $WL_INC $WL_END))
wl_range is a string consisting of space-delimited numbers, not an array. Your for loop should simply look like
for i in $wl_range; do
WL[i]=$i
done
That said, don't use the for loop; use #IgnacioVazquez-Abrams' answer.

Shell script split a string by space

The bash shell script can split a given string by space into a 1D array.
str="a b c d e"
arr=($str)
# arr[0] is a, arr[1] is b, etc. arr is now an array, but what is the magic behind?
But, what exactly happened when we can arr=($str)? My understanding is the parenthesis here creates a subshell, but what happen after that?
In an assignment, the parentheses simply indicate that an array is being created; this is independent of the use of parentheses as a compound command.
This isn't the recommended way to split a string, though. Suppose you have the string
str="a * b"
arr=($str)
When $str is expanded, the value undergoes both word-splitting (which is what allows the array to have multiple elements) and pathname expansion. Your array will now have a as its first element, b as its last element, but one or more elements in between, depending on how many files in the current working directly * matches. A better solution is to use the read command.
read -ra arr <<< "$str"
Now the read command itself splits the value of $str without also applying pathname expansion to the result.
It seems you've confused
arr=($str) # An array is created with word-splitted str
with
(some command) # executing some command in a subshell
Note that
arr=($str) is different from arr=("$str")in that in the latter, the double quotes prevents word splitting ie the array will contain only one value -> a b c d e.
You can check the difference between the two by the below
echo "${#arr[#]}"

removing lines and characters while reading into an array

Trying to write a shell script that will read in a text file which looks something like:
Line A needs to be removed
Line B also to be removed
Line C which has lots of things, including characters that need removing should be the first to be read into an array position [0]
Line D
.
.
Line "n"
What I need to do is read from line C up to line n-1 into an array, but also remove the first 4 characters and the last 2 characters of the useful lines (Line C to Line n-1).
I can't seem to do anything other than read in the entire list, or print/echo the partial list but can't get that into an array.
I'm happy to multi-step it, rather than do it all in one line, but what ever is clean.
Try this if works
head -n-1 txt | awk '{if($0~/LineC/){i=1}; if(i>0){print substr($0,5,length($0)-2)}}' txt

How do I get the output of an object which has more than one line in Perl?

#ver = $session->cmd("sh conf");
The variable here is ver, which has the configuration file, that is, it has more than one line. So how to take an output of each line of the ver variable without putting it in a loop?
Your #var variable is an array - each element will contain one line.
You cannot get all lines without (implicitly or explicitly) looping over the entire array.
You can have perl do all the work for you though - for example, using join, grep or map, depending what you want.
Examples:
#print all lines to a webpage
print join('<br />',#ver);
#print all lines with the word 'error' in it
print grep(/error/,#ver);
How about :
print join("\n", #ver);

Resources