I am trying to increment a number in the middle of the string. Tried many ways but didn't find a solution. Any ideas in shell script
Ex:- i have a string sam_2.0_protected_dev_branch. I want to increment the number at the middle of the string. So the output should look like
sam_2.0_kumar_dev_branch
sam_2.1_kumar_dev_branch
sam_2.2_kumar_dev_branch
...
Maybe instead of trying to change the string, divide it in 3 parts. text, number and text. you can increment the number and then make one string with that 3 parts.
Sorry if the terminology isn't right
here is a proper documentation: https://ss64.com/ps/syntax-concat.html
Code :
$version = 1.0
$nameOne = "sam_"
$nametwo = "_protected_dev_branch"
for ($i = 1; $i -lt 5; $i++)
{
$fullName = $nameOne + $version + $nametwo
Write-Host $fullName
$version = $version + 0.1
}
Output :
sam_1_protected_dev_branch
sam_1.1_protected_dev_branch
sam_1.2_protected_dev_branch
sam_1.3_protected_dev_branch
there's a way to to force a number to show number of numbers after the comma, but I will let you deal with it
$version = 1
for ($i = 1; $i -lt 5; $i++)
{
$fullName = "sam_2." + $version + "_protected_dev_branch"
Write-Host $fullName
$version = $version + 1
}
Related
Have seen people using the following for loop
for (( i = 0; i <= $length; i++ ))
Can I omit the $ sign in double parentheses to refer the variable length?
Definitely you can do that as following:
length='10'
for (( i = 0; i <= length; i++ ))
do
echo "I = $i"
done
Output:
I = 0
I = 1
I = 2
I = 3
I = 4
I = 5
I = 6
I = 7
I = 8
I = 9
I = 10
Yes, in fact, ShellCheck encourages it.
As your shell interpreter is bash, if your length is known I would recommend you using a neat feature called bash sequence expression:
for each in {0..10}
do
echo $each
done
I am getting the above error when using Freds ImageMagick Textdeskew Script The error looks like this:
awk: line 38: syntax error at or near *
/home/work/textdeskew: line 468: regression_Arr: bad array subscript
/home/work/textdeskew: line 474: regression_Arr: bad array subscript
The lines the errors fall on look like this:
angle=`echo ${regression_Arr[rnum-1]} | cut -d: -f2` line 468
# set rotation to be correct for -90<=angle<90 (+90 will be upside downs)
rotation=`convert xc: -format "%[fx:$angle<0?-($angle+90):-($angle-90)]" info:`
rotation=`convert xc: -format "%[fx:abs($rotation)<0.00001?0:$rotation]" info:`
# remove outliers, if res_ave > res_thresh
res_ave=`echo ${regression_Arr[rnum-7]} | cut -d: -f2` line 474
Im assuming the error is because rnum is 0. But im unsure on how to read and debug the script to resolve the error as this may not even be the case. Here is where rnum and regression_Arr are declared:
linearRegression()
{
Arr="$1"
regression_Arr=(`echo "${Arr[*]}" | awk \
'BEGIN { FS = ","; RS = " "; pi = atan2(0, -1); }
NF == 2 { x_sum += $1
y_sum += $2
xy_sum += $1*$2
x2_sum += $1*$1
y2_sum += $2*$2
num += 1
x[NR] = $1
y[NR] = $2
}
END { mean_x = x_sum / num
mean_y = y_sum / num
for (i = 1; i <= num; i++) {
delx = (x[i]-mean_x)
dely = (y[i]-mean_y)
numerator += delx*dely
denominator += dely*dely - delx*delx
}
phi = 0.5*atan2(-2*numerator,denominator)
r = mean_x*cos(phi)+mean_y*sin(phi)
if ( sqrt(phi*phi) < 0.0001 ) {
angle = -90
}
else {
slope = -cos(phi)/sin(phi)
inter = r/sin(phi)
angle = (180/pi)*atan2(slope,1)
}
for (j = 1; j <= num; j++) {
delr = (x[j]*cos(phi)+y[j]*sin(phi)-r)
res_sq = delr*delr
sum_res_sq += res_sq
res = sqrt(delr*delr)
sum_res += res
print "Residual"j":"res
}
res_ave = sum_res/num
res_std = sqrt((sum_res_sq/num)-(sum_res/num)**2)
print "res_ave:"res_ave
print "res_std:"res_std
print "phi:"phi
print "r:"r
print "Slope:"slope
print "Intercept:"inter
print "Angle:"angle
}'`)
rnum=${#regression_Arr[*]}
if $debug; then
echo ""
echo "rnum=$rnum;"
# list regression data
for ((ii=0; ii<rnum; ii++)); do
echo "${regression_Arr[$ii]}"
done
fi
}
I wonder if this script used to work and now doesnt due to updates in the code?
This was fixed by installing gawk and following a new error bc. Huge thanks to #fmw42 for helping through this on the ImageMagick forums.
Good evening, i have a bioperl code to count the number of sequences in a fasta file, but i am trying to modify the code to count sequences shorter than 20 and longer from 120 in any given fasta file. The code is below
use strict;
use Bio::SeqIO;
my $seqfile = 'sequences.fa';
my $in = Bio::SeqIO->new
(
-format => 'fasta',
-file => $seqfile
) ;
my $count = 0;
while (my $seq = $in->next_seq)
{
$count++;
}
print "There are $count sequences\n";
You can use the length function of the sequence object to construct an if statement inside your while loop.
my $len = $seq->length();
if($len < 20 || $len > 120){
$count++;
}
The PowerShell should print all 16-bit binary number with leading zeroes like this:
0000000000000000
0000000000000001
0000000000000010
0000000000000011
...
1111111111111100
1111111111111101
1111111111111110
1111111111111111
My current code looks like this:
0 .. 65535 | % { "{0:D16}" -f [int64][convert]::ToString($_,2) }
But I am wondering if there are other algorithms that would perform the task faster.
tl;dr The following approach using caching and an array look-up is faster, but such may not be realized due to other bottlenecks.
Here is a version which uses caching. However, as per Measure-Command there is no significant improvement (3.5 vs 3.8 elapsed seconds) - I was expecting to see a much larger difference.
$l = #(0) * 256
0..255 | % {
$l[$_] = "{0:D8}" -f [int64][convert]::ToString($_,2)
}
0 .. 65535 | % {
$l[$_ / 256 ] + $l[$_ -band 255] # no -shr in PS before 3.0
}
There are two "slow" parts with this problem. One is the use of %{} is slow compared to a plain loop. Using the above modified to the following (which isn't very useful) completes in 0.3 seconds.
For ($i = 0; $i -lt 65535; $i = $i + 1) {
$line = $l[$i / 256 ] + $l[$i -band 255]
}
While a similarly modified, and equally useless, version of the original completes in 0.5 seconds. This is a good bit slower than the cached proposed version, even though the proposed approach does not ultimately affect the bottleneck or wall-clock.
For ($i = 0; $i -lt 65535; $i = $i + 1) {
$line = "{0:D16}" -f [int64][convert]::ToString($i,2)
}
Usefully collecting output manually, with a presized array, is also much faster than %{} and it runs in 0.5 seconds for my version - it will run a bit slower for the original approach, say 0.8 seconds.
$r = #("") * 65536
# ..
For ($i = 0; $i -lt 65535; $i = $i + 1) {
$r[$i] = $l[$i / 256 ] + $l[$i -band 255]
}
Secondly, actually materializing with Write-Output is very slow and is slower than collecting the result with %{}. Using either Write-Output or Write | Output-File .. results in times exceeding 8 seconds.
$r = #("") * 65536
$l = #(0) * 256
For ($i = 0; $i -lt 256; $i = $i + 1) {
$l[$i] = "{0:D8}" -f [int64][convert]::ToString($i, 2)
}
For ($i = 0; $i -lt 65535; $i = $i + 1) {
$r[$i] = $l[$i / 256 ] + $l[$i -band 255]
}
# to here in about 0.5 seconds
Write $r | Out-File results.txt
# almost another 8 seconds to get here
In the same thread as this question, I am giving this another shot and ask SO to help address how I should take care of this problem. I'm writing a bash script which needs to perform the following:
I have a circle in x and y with radius r.
I specify resolution which is the distance between points I'm checking.
I need to loop over x and y (from -r to r) and check if the current (x,y) is in the circle, but I loop over discrete i and j instead.
Then i and j need to go from -r/resolution to +r/resolution.
In the loop, what will need to happen is echo "some_text i*resolution j*resolution 15.95 cm" (note lack of $'s because I'm clueless). This output is what I'm really looking for.
My best shot so far:
r=40.5
resolution=2.5
end=$(echo "scale=0;$r/$resolution") | bc
for (( i=-end; i<=end; i++ ));do
for (( j=-end; j<=end; j++ ));do
x=$(echo "scale=5;$i*$resolution") | bc
y=$(echo "scale=5;$j*$resolution") | bc
if (( x*x + y*y <= r*r ));then <-- No, r*r will not work
echo "some_text i*resolution j*resolution 15.95 cm"
fi
done
done
I've had just about enough with bash and may look into ksh like was suggested by someone in my last question, but if anyone knows a proper way to execute this, please let me know! What ever the solution to this, it will set my future temperament towards bash scripting for sure.
You may want to include the pipe into bc in the $()'s. Instead of.
end=$(echo "scale=0;$r/$resolution") | bc
use
end=$(echo "scale=0;$r/$resolution" | bc)
should help a bit.
EDIT And here's a solution.
r=40.5
resolution=2.5
end=$(echo "scale=0;$r/$resolution" | bc)
for i in $(seq -${end} ${end}); do
for j in $(seq -${end} ${end}); do
x=$(echo "scale=5;$i*$resolution" | bc)
y=$(echo "scale=5;$j*$resolution" | bc)
check=$(echo "($x^2+$y^2)<=$r^2" | bc)
if [ ${check} -eq '1' ]; then
iRes=$(echo "$i*$resolution" | bc)
jRes=$(echo "$j*$resolution" | bc)
echo "some_text $iRes $jRes 15.95 cm"
fi
done
done
As already mentioned this problem is probably best solved using bc, awk, ksh or another scripting language.
Pure Bash. Simple problems which actually need floating point arithmetic sometimes can be transposed to some sort of fixed point arithmetic using only integers. The following solution simulates 2 decimal places after the decimal point.
There is no need for pipes and external processes inside the loops if this precision is sufficient.
factor=100 # 2 digits after the decimal point
r=4050 # the representation of 40.50
resolution=250 # the representation of 2.50
end=$(( (r/resolution)*factor )) # correct the result of the division
for (( i=-end; i<=end; i+=factor )); do
for (( j=-end; j<=end; j+=factor )); do
x=$(( (i*resolution)/factor )) # correct the result of the division
y=$(( (j*resolution)/factor )) # correct the result of the division
if [ $(( x*x + y*y )) -le $(( r*r )) ] ;then # no correction needed
echo "$x $y ... "
fi
done
done
echo -e "resolution = $((resolution/factor)).$((resolution%factor))"
echo -e "r = $((r/factor)).$((r%factor))"
you haven't heard of (g)awk ??. then you should go learn about it. It will benefit you for the long run. Translation of your bash script to awk.
awk 'BEGIN{
r=40.5
resol=2.5
end = r/resol
print end
for (i=-end;i<=end;i++) {
for( j=-end;j<=end;j++ ){
x=sprintf("%.5d",i*resol)
y=sprintf("%.5d",j*resol)
if ( x*x + y*y <= r*r ){
print ".......blah blah ......"
}
}
}
}'
It's looking more like a bc script than a Bash one any way, so here goes:
#!/usr/bin/bc -q
/* -q suppresses a welcome banner - GNU extension? */
r = 40.5
resolution = 2.5
scale = 0
end = r / resolution
scale = 5
for ( i = -end; i <= end; i++ ) {
/* moved x outside the j loop since it only changes with i */
x = i * resolution
for ( j = -end; j <= end; j++ ) {
y = j * resolution
if ( x^2 * y^2 <= r^2 ) {
/*
the next few lines output on separate lines, the quote on
a line by itself causes a newline to be created in the output
numeric output includes newlines automatically
you can comment this out and uncomment the print statement
to use it which is a GNU extension
*/
/* */
"some_text
"
i * resolution
j * resolution
"15.95 cm
"
/* */
/* non-POSIX:
print "some_text ", i * resolution, " ", j * resolution, " 15.95 cm\n"
*/
}
}
}
quit