I want to use bash script to generate some files. The file names will be in the format 2_x.yRandom.txt, where x is 2, 4, 6, 8, 10 and y is from 1 to 5.
eg. "2_2.2Random.txt" or "2_4.3Random.txt"
This is my script:
#Generate input for sort1
for i in 2 4 6 8 10
do
for j in 1 2 3 4 5
do
java utils.StringGenerator r 2 $i > "2_$i.$jRandom.txt"
java utils.StringGenerator s 2 $i > "2_$i.$jSorted.txt
java utils.StringGenerator v 2 $i > "2_$i.$jReversed.txt
done
done
The output file is always 2_2..txt or 2_4..txt, it seems that $j is not in the output.
What am I doing wrong?
Thanks!
PS: I'm using a Mac.
You forgot to tell bash where the variable name ends.
java utils.StringGenerator r 2 $i > "2_$i.${j}Random.txt"
Related
This question already has an answer here:
Command Line Arguments vs Input - What's the Difference?
(1 answer)
Closed 12 months ago.
I have for example a user with a set of numbers. How can I make bash add them together?
Example in one go the user enters
(The amount of numbers they enter is up to them and it is unknown)
bash file 3 1 5 2 2 4
How can I make bash return 17 directly from that example?
I tried
#!/usr/bin/env sh
sum=0
while read number && [ -n "$number" ]; do
sum=$((sum + ${number/#-}))
echo "$sum"
done
But this is not clean and it is returning
$ bash file
3
3
1
4
5
9
2
11
2
13
4
17
I instead want the user to only place their numbers in 1 go and not be there to put more and more numbers
Instead of having them excute the command like I have it like
bash file
1
3
4
etc
instead I want to do it in 1 go
bash file 1 3 5 6
How?
You can loop through all script arguments and calculate sum:
#!/usr/bin/env sh
sum=0
for i in "$#"; do
sum=$(( $sum + $i ))
done
echo $sum
Running with your example:
$ bash sum 3 1 5 2 2 4
17
example:
for i in 1 2 3 4, j in 7 8 9 0
do
echo $i"="$j
done
output:
1=7
2=8
3=9
4=0
i know this code will throw you a lot of error right away, but is there any way?
There is no such thing in Bash, but you can get your desired output:
foo=(1 2 3 4)
bar=(7 8 9 0)
for (( i=0; i<${#foo[#]}; i++ ))
do
echo "${foo[$i]}=${bar[$i]}"
done
I have a rather costly shell command which generates some output which is supposed to be plotted. The output contains information for several curves, e. g. like this:
echo 1 2 3; echo 4 5 6; echo 7 8 9
They are supposed to be plotted using a command like this:
plot <something> using 1:2, \
<something> using 1:3
To avoid calling the shell command repeatedly (as it is rather slow), I want to store its result in a datablock, but up to now my trials didn't work. Here is what I tried:
output = system("echo 1 2 3; echo 4 5 6; echo 7 8 9")
set print $DATA
print output
unset print
Now I seem to have a datablock containing what I want because print $DATA now prints this:
1 2 3
4 5 6
7 8 9
The trailing blank line I hope isn't a problem but maybe it indicates that there is something wrong, I don't know.
When I now try to plot this with plot $DATA using 1:2 I only get the first of the three expected points (1|2), (4|5), and (7|8).
I feel there is probably an easier way to achieve my original goal but up to now I didn't find it.
Now I seem to have a datablock containing what I want because print $DATA now prints this:
1 2 3
4 5 6
7 8 9
No, $DATA does not contain what you want. $DATA should be an array with three elements: 1st element is 1 2 3, 2nd element is 4 5 6, and 3rd one is 7 8 9. Instead, the combination of output = system("..."), set print $DATA, and print output generates an array with only one element: 1 2 3\n4 5 6\n7 8 9, printing into a datablock does not split the string into separate lines.
The difference is not visible with print $DATA. Both, a new array element of the datablock as well as a \n within an array element generate a linebreak.
You can use the load '< XXXXX' command to generate a useful datablock. From the gnuplot documentation:
The load command executes each line of the specified input file as if it had been typed in interactively.
...
On some systems which support a popen function (Unix), the load file can be read from a pipe by starting the file name with a '<'.
The "XXXXX" can be a series of shell commands which generate the necessary gnuplot commands:
load '< echo "\$DATA << EOD" && echo 1 2 3; echo 4 5 6; echo 7 8 9 && echo "EOD"'
print $DATA
plot $DATA using 1:2 pt 5, $DATA using 1:3 pt 7
(inspired by gnuplot: load datafile 1:1 into datablock)
Assuming I understood your problem correctly, I see three versions where versions 2 and 3 should work. I guess version 2 is what you wanted to avoid. Why the 1st version does not work I only can guess. My suspicion is something with the line end character. There seems to be a difference if you write to a datablock (version 1) or to a file (version 3). I remember a discussion with #Ethan about this... but I still don't understand myself. I assume you're working with Linux, in Windows & is used instead of ;.
Code:
### system output to datablock
reset session
# Version 1
set title "Version 1: only plots 1st data line"
output = system("echo 1 2 3 & echo 4 5 6 & echo 7 8 9") # in Windows "&" instead of ";"
set print $Data
print output
set print
plot $Data u 1:2 w lp pt 7
pause -1
# Version 2
set title "Version 2: several system calls"
set print $Data
print system("echo 1 2 3")
print system("echo 4 5 6")
print system("echo 7 8 9")
set print
plot $Data u 1:2 w lp pt 7
pause -1
# Version 3
set title "Version 3: writing into data file"
output = system("echo 1 2 3 & echo 4 5 6 & echo 7 8 9") # in Windows "&" instead of ";"
set print "Data.dat"
print output
set print
plot "Data.dat" u 1:2 w lp pt 7
### end of code
I have a text file containing a line of various numbers (i.e. 2 4 1 7 12 1 4 4 3 1 1 2)
I'm trying to get the index for each occurrence of 1. This is my code for what I'm currently doing (subtracting each index value by 1 since my indexing starts at 0).
eq='0'
gradvec=()
count=0
length=0
for item in `cat file`
do
((count++))
if (("$item"=="$eq"))
then
((length++))
if (("$length"=='1'))
then
gradvec=$((count -1))
else
gradvec=$gradvec' '$((count - 1))
fi
fi
done
Although the code works, I was wondering if there was a shorter way of doing this? The result is the gradvec variable being
2 5 9 10
Consider this as the input file:
$ cat file
2 4 1 7 12 1
4 4 3 1 1 2
To get the indices of every occurrence of 1 in the input file:
$ awk '$1==1 {print NR-1}' RS='[[:space:]]+' file
2
5
9
10
How it works:
$1==1 {print NR-1}
If the value in any record is 1, print the record number minus 1.
RS='[[:space:]]+'
Define the record separator as one or more of any kind of space.
Is it possible to do something like this in bash with cut:
strLf="JJT9879YGTT"
strZ=(2, 3, 5, 6, 9, 11)
numZ=${#strZ[#]}
for ((ctZ=0; ctZ<${numZ}; ctZ++))
do
lenThis=${strZ[${ctZ}]}
fetch=$(echo "${strLf}" | cut -c 1-${lenThis})
done
Through successive loops, I want ${fetch} to contain "JJ" "JJT" "JJT98" "JJT987" "JJT9879YG" "JJT9879YGTT", etc, according to the indexes given by strZ.
Or is there some other way I need to be doing this?
You can use ${string:position:length} to get the length characters of $string starting in position.
$ s="JJT9879YGTT"
$ echo ${s:0:2}
JJ
$ echo ${s:0:3}
JJT
And also using variables:
$ t=5
$ echo ${s:0:$t}
JJT98
So if you put all these values in an array, you can loop through them and use its value as a length argument saying ${string:0:length}:
strLf="JJT9879YGTT"
strZ=(2 3 5 6 9 11)
for i in ${strZ[#]}; do
echo "${strLf:0:$i}"
done
For your given string it returns this to me:
$ for i in ${strZ[#]}; do echo "${strLf:0:$i}"; done
JJ
JJT
JJT98
JJT987
JJT9879YG
JJT9879YGTT
words="JJT9879YGTT"
strZ=(2 3 5 6 9 11)
for i in "${strZ[#]}"
do
echo ${words:0:$i}
done
Output:
JJ
JJT
JJT98
JJT987
JJT9879YG
JJT9879YGTT
DEMO
Realised my mistake - I was using commas in the array to identify elements.
So instead of what I was using:
strZ=(2, 3, 5, 6, 9, 11)
I have to use:
strZ=(2 3 5 6 9 11)
It works for cut as well.