How to output specific cells of an array in bash? - arrays

Say I've got the following array:
items[0]=0
items[1]=1
items[2]=2
etc.
Using echo/printf, how would I output only specific cells, for instance only cells 0,2,4.
So far I've got this:
echo "${items[*]}"
This outputs all of the array, but how would I alter this line to make it only output the specified cells? I'm pretty sure I'm just missing what the syntax for this is.
Edit: Sorry, I inaccurately described what I'm asking. What I need to find out, is how to output the specified data point by calling the array only once.
For instance:
echo ${items[magical code stuff here]magical code stuff here too maybe}"

Replace the * with 0 2 4:
echo "${items[0]} ${items[2]} ${items[4]}"

Related

Passing an array as an argument from a Perl script to a R script

I am new to R and I have a Perl Script in which I want to call a R Script, which calculates something for me (not important what in this context). I want to give as arguments an input file, an array which contains some numbers and a number for a total number of clusters. medoid.r is the name of my R Script.
my $R_out;
$R_out = qx{./script/medoid.r $output #cluster $NUMBER_OF_CLUSTERS}
My current R code looks like this. Right now I just print cluster to see what is inside.
args <- commandArgs(TRUE)
filename = args[1]
cluster = as.vector(args[2])
number_of_cluster = args[3]
matrix = read.table(filename, sep='\t', header=TRUE, row.names=1, quote="")
print(cluster)
Is it possible to give an array as an argument? How can I save it in R? Right now only the first number of the array is stored and printed, but I would like to have every number in a vector or something similar.
If you do this in Perl
$R_out = qx{./script/medoid.r $output #cluster $NUMBER_OF_CLUSTERS};
your command line will look similar to this
./scriptmedoid.r output 111 222 333 3
assuming that $output is 'output' and #clusters = (111, 222, 333).
If you want to read that in R, you need to assign all elements after the first one in args to cluster but the last one, and the last one to number_of_cluster. In Perl you can use shift and pop for that.
my #args = #_;
my $output = shift #args;
my $number = pop #args;
# now #args only contains the clusters
I don't know if those operators exist in R.
You cannot pass a full data structure unless you serialize it in some way.
In perl, qx will expect a string as an argument. You may certainly use an array to generate that string, but ultimately it will still be a string. You cannot "pass an array" to a system call, you can only pass command-line text/arguments.
Keep in mind, you are executing a system call running Rscript as a child process. The way you're describing the issue, there is no inter-process communication beyond the command line. Think of it this way: how would you type an array on the command line? You may have some textual way of representing an array, but you can't type an array on the command line. Arrays are stored and accessed in memory differently by various different languages, and thus are not really portable between two languages like you're suggesting.
One solution: all that said, there may be a simple solution for you. You haven't provided any information on the type of data you want to pass in your array. If it is simple enough, you may try passing it on the command line as delimited text, and then break it up to use in your Rscript.
Here is an Rscript that shows you what I mean:
args = commandArgs(trailingOnly=TRUE)
filename = args[1]
cluster <- c(strsplit(args[2],"~"))
sprintf("Filename: %s",filename)
sprintf("Cluster list: %s",cluster)
print("Cluster:")
cluster
sprintf("First Item: %s",cluster[[1]][1])
Save it as "test.r" and try executing it with "Rscript test.r test.txt one~two" and you'll get the following output (tested on Rscript 46084, OpenBSD):
[1] "Filename: test.txt"
[1] "Cluster list: c(\"one\", \"two\")"
[1] "Cluster:"
[[1]]
[1] "one" "two"
[1] "First Item: one"
So, all you'd have to do on the perl side of things is join() your array using "~" or any other delimiter- it is highly dependent on your data, and you haven't provided it.
Summary: re-think how you want to communicate between perl and Rscript. Consider sending the data as a delimited string (if it's the right size) and breaking it up on the other side. Look into IPC if that won't work, consider environment variables or other options. There is no way to send an array reference on the command-line.
Note: you may want to read up on security risks of different system calls in perl.

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.

trying to use while read loop to save result to an array

Quick question, can i do this?:
while IFS=: read menu script
do
echo "$x. $menu"
command[x]="$script"
let x++
done < file.txt
read two strings per line from a file, print one and save the other to an array..
file.txt looks like this:
File Operations:~/scripts/project/File_Operations.sh
Directory Operations:~/scripts/project/Directory_Operations.sh
Process Management:~/scripts/project/Process_Management.sh
Search Operations:~/scripts/project/Search_Operations.sh
Looks right. 2 things.
You need to initialise x. x=0
When you use x as a subscript it needs the $. i.e. command[$x]="$script"
And done forget the {}s when referencing the command array. e.g. ${command[0]}
What shell are you using? Works for me in bash, I just prepended the following two lines to the script:
#!/bin/bash
x=0
Without setting $x to 0, the user is presented with
. File Operations
1. Directory Operations
2. Process Management
3. Search Operations

Linux Bash pass function argument to array name

I'm working on a script that has a number of functions in place which pull data from a few different arrays. We hope to keep the arrays individualized for reporting purposes. The information in the arrays does not change and the only thing different between each function is which array name is being used. Since all of the functions have 98% the same content I'm trying to pull them into 1 single array for simplified management.
The issue I'm facing though is that I'm not able to figure out the correct syntax to obtain the length of an array based on the array title that is passed in the function argument. I can't post the actual script, but here is a mock up that details a simplified version of what I'm testing with. I believe if we can get it working using the mock script below I can transfer the needed changes to the actual script.
array1=(
"item1 123"
"item2 456"
)
array2=(
"stockA qwe"
"stockB asd"
"stockC zxc"
)
test() {
local ref=${1}[#]
IFS=$'\n'; for i in ${!ref}; do echo $i ; done
}
test array1
test array2
The script above so far will echo the content of each array line based on argument 1 when the function and it's argument is called; which is working as needed. I've tried many different combinations such as len=${#${1}[#]} but I always receive a "bad substitution" error. The functions I mention before have while loops and for statements that use the array length to know when to stop, so being able to pull that information really ties it all together. What I'm hoping for is something like the flow below
I plan to continue my research on this, but thank you for any help and knowledge that can be provided!
-Cyanide
I think the only solution is to create a copy of the array, then take the length of that array:
local ref=${1}[#]
copy=( "${!ref}" )
len=${#copy[#]}
Since bash does not allow chaining of the parameter expansion operators, I know of no shorter way to use both ${#...} and ${!...} on the same line.

Executing nested loops+foreach+csh

It's been a while since I used csh formatting and I am having a little bit of trouble with a few things. Things seem so much easier to execute in Matlab, however I need to do this on the terminal because of the programs I am trying to interact with.
So here's what I want to do: I have a file del.txt that is structured like this
1
2
3
4
etc. So each value is in it's own row and there's one column for all the data. I have a bunch of other files that are within my directory. I want to match up say value 1 (which in this case is 1) with file 1 and value 2 with file 2, etc and so on and so forth. So here's what I did...
Code:
!/bin/csh
foreach a (cat del.txt)
foreach sta(ls *.HHZ)
echo a is $a
echo $sta
cat <<END>>macro.m
r $a
r $sta
END
sac macro.m
rm macro.m
end
end
However what I achieve is that it loops through all of the values in del.txt and each file and then moves on to the next file within my directory and loops through all of the values. I'm having trouble figuring out the format that this should be in to match up the correct values. I'm not doing much within the script yet until I can get them to match up. Please help Can someone tell me what I'm doing wrong? I read that the foreach command will execute all the commands on each file..but haven't been able to find a way to get around this. What I want it to do is take value 1 from del.txt and match it up with file 1 (sta) from the directory finish the loop, then take value 2 from del.txt and match it up with file 2 from the directory (sta). I've never done more than just simple iterations with csh on one subset of files, and I am not sure how to reference the values to one another. Any help would be greatly appreciated. I haven't found a simple way to do this without writing everything out. I looked at the 'for' and 'while' commands..if there is a simple way to do it I'm not seeing it.
Cheers,
K
IF I am understanding correctly, You have a txt file will list of strings and you want it to match with the files.
I am assuming by this particular statement of yours:
I want to match up say value 1 (which in this case is 1) with file 1
You mean to match the string at 1 with file name of file 1.
Here's a possible solution based on this assumption(this will help you anyway with loop):
#Store value in file.txt in a array
set file_var = `cat file.txt`
#Store file list in my_dir in a var
set my_dir = <your dir path>
set file_list_var = `ls $my_dir`
#Let's print "file Match: for every match
foreach var1 ($file_var)
foreach var2 ($file_list_var)
if("$var1" == "$var2") echo $var1 = $var2 : Match Found.
endif
endif

Resources