I am trying to generate a password with certain requirements.
When I enter the while loop to generate a random character from the array it is fine until I add a count for my index "$i"
With the following code:
#!/bin/bash
#SET ARRAY VALUES
all=( 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z )
echo
#SET COUNT VALUES TO 0
numc=0
lowc=0
upc=0
i=0
while true;
do
#GENERATE PASSWORD
phrase[$i]=${all[$RANDOM%62]}
#CHECK IF PASSWORD MEETS REQUIREMENTS
for ((n=0; n<10; n++))
do
if [ ${phrase[$i]} == ${all[$n]} ]
then
echo num ${all[$n]}
let "numc++"
let "i++"
fi
done
I get the error "line 39: [: ==: unary operator expected"
but if I remove the let "i++" line then there is no error. But I need to increase my index in order to exit the loop and check the minimum length of the password
If ${phrase[$i]} (by the way you don't need $ in [$i] context ${phrase[i]} works too) is ever the empty string that if test will become [ == value-of-all-n ] which isn't a valid test.
Either quote the variables (which is almost always the right thing to do) or prevent that from ever being the empty string. (Was that i++ supposed to happen outside the inner loop?)
Related
I need help writing a script for batch.
I forgot the password for a file, it's a simple password 4 chars ( 1234, asdf, qwer) .
The command line is this:
C:\Users\DB> .\open.exe --file=db1.bin --password=asdf
Logging to C:\Users\DB\open.log
Error: failed to load: invalid password
I managed to generate a list of passwords (pass.txt) since the number is either 1st or last in string and only lower case but still there are couple thousands. Is there any way to automate this?
To iterate over a text file, use a for /f loop.
for /f %%A in (pass.txt) do open.exe --file=db1.bin --password=%%A
If you want it to track where you are in the file, add an echo.
for /f %%A in (pass.txt) do (
echo Now trying %%A
open.exe --file=db1.bin --password=%%A
)
#echo off
(
for %%a in (0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
for %%b in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
for %%c in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
for %%d in (0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
echo(%%a%%b%%c%%d
)
)
)
)
)>pass.txt
needs about half a minute to generate all possible 808496 passwords
{letter | number}{letter}{letter}{letter | number}
where only start OR end may be a number). If both start AND end could be a number, just skip the last two lines (876096 passwords)
I have two arrays, which are arrAlpha[] and arrPT[]. Array arrAlpha contains the Alphabets and array arrPT[] contains some of the plain letters.following is the code that i wrote in bash shell script to compare elements of both arrays and to store the position elements of arrPT[] in arrAlpha[] to array arrT[]. But when i run i feel like something is wrong in if statement to print out the elements in arrT[]. can anyone help me please?
#!/bin/bash
arrAlpha=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
arrPT=(E K N R S W )
lenPT=${#arrPT}
declare -A arrT
q=0
for((i=0; i<lenPT; i++)) do
for((j=i; j<26; j++)) do
if [ ${arrPT[$i]} = ${arrAlpha[$j]} ]; then
arrT[$q]=$j % 26;
((++q));
fi
done
done
echo ${arrAlpha[#]}
echo ${arrPT[#]}
echo ${arrT[#]}
the expected output is to change elements arrPT to number 0 to 25.
arrAlpha=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
arrPT =(E K N R S W)
arrT =(4 10 13 17 18 22)
Here's a fixed version of your script - there are some style changes that I prefer
arrAlpha=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
arrPT=(E K N R S W )
# array length needs index *
lenPT=${#arrPT[*]}
# seems arrT can be simple indexed array
declare -a arrT
q=0
for((i=0; i<lenPT; ++i)); do
for((j=0; j<26; ++j)); do
if [[ ${arrPT[i]} == ${arrAlpha[j]} ]]; then
# arithmetic inside $(())
arrT[q++]=$((j % 26))
fi
done
done
echo ${arrAlpha[#]}
echo ${arrPT[#]}
echo ${arrT[#]}
The main bug is with this line:
lenPT=${#arrPT}
which should be written like:
lenPT=${#arrPT[#]}
But, in fact, there is no need (even if it is not wrong to use it) for such variable, change this line:
for((i=0; i<lenPT; i++)) do
to:
for((i=0; i<${#arrPT[#]}; i++)) do
Some other issues:
There is no need to mod 26 the value of $j, it will never reach 26.
The array arrT seems to be an indexed array: -a no need for -A.
There is no need for variable q if each result will be in the same position as the index i
Please quote your expansions.
Use printf (more reliable) instead of echo.
The script with all the above done is:
#!/bin/bash
arrAlpha=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
arrPT=(E K N R S W )
declare -a arrT
for((i=0; i<${#arrPT[#]}; i++)) do
for((j=i; j<${#arrAlpha[#]}; j++)) do
[[ ${arrPT[i]} == "${arrAlpha[j]}" ]] && let arrT[i]=j
done
done
printf '%s ' "${arrAlpha[#]}" ; echo
printf '%3s ' "${arrPT[#]}" ; echo
printf '%3s ' "${arrT[#]}" ; echo
Of course, the second loop could be removed by cutting that string at the character:
#!/bin/bash
Alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZ
arrPT=(E K N R S W )
declare -a arrT
for((i=0; i<${#arrPT[#]}; i++)) do
arrT[i]=${Alpha%"${arrPT[i]}"*} # cut the string at the character.
arrT[i]=${#arrT[i]} # Use the len of the cut string.
done
printf '%s ' "$Alpha" ; echo
printf '%3s ' "${arrPT[#]}" ; echo
printf '%3s ' "${arrT[#]}" ; echo
I have a array/ named vector that looks like this:
d f g
1 2 3
I want to fill up the empty slots, meaning I want this:
a b c d e f g
0 0 0 1 0 2 3
Is there an elegant way of doing this, without having to write loops and conditionals? In my actual problem, instead of abcd as my array names, it's numbers. Not sure if that makes a difference. Figured alphabet is easier to understand for a reproducible example.
Create a vector of the final names, nms and then create a named vector of zeros from it using sapply and replace the elements corresponding to input names with the input values.
v <- c(d = 1, f = 2, g = 3) # input
nms <- letters[letters <= max(names(v))] # names on output vector, i.e. letters[1:7]
replace(sapply(nms, function(x) 0), names(v), v) ##
giving:
a b c d e f g
0 0 0 1 0 2 3
If in your actual vector the names are not letters then just set nms yourself. For example, nms <- c("dogs", "cats", "d", "elephants", "f", "g") would work with the same line marked ## above.
2) An alternative is to replace the line marked ## above with:
unlist(modifyList(as.list(setNames(numeric(length(nms)), nms)), as.list(v)))
Data
x <- c(d=1L,f=2L,g=3L);
x;
## d f g
## 1 2 3
Solution 1: First match new names into x and extract values, then replace NAs with zero.
x <- setNames(x[match(letters[1:7],names(x))],letters[1:7]);
x[is.na(x)] <- 0L;
x;
## a b c d e f g
## 0 0 0 1 0 2 3
Solution 2: One-liner, using nomatch argument of match().
setNames(c(x,0L)[match(letters[1:7],names(x),nomatch=length(x)+1L)],letters[1:7]);
## a b c d e f g
## 0 0 0 1 0 2 3
When I run the script I enter a single argument. I want to store the argument into a variable and access it as a string. So if I enter $ ./script foo I should be able to access f, o, and o. So echo $pass[0] should display f
but what I am finding is that $pass is storing the argument as one piece
so echo $pass[0] displays foo
How do I access the different positions in the string?
#!/bin/bash
all=( 0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z )
pass=$1
max=${#pass}
for (( i=0; i<max; i++ ))
do
for (( n=0; n<10; n++ ))
do
if [ "${pass[$i]}" == ${all[$n]} ]
then
echo true
else
echo false i:$i n:$n pass:${pass[$i]} all:${all[$n]}
fi
done
done
To spell out Etan's comment in the context of this question:
set -- "my password"
chars=()
for ((i=0; i<${#1}; i++)); do chars+=("${1:i:1}"); done
declare -p chars
outputs
declare -a chars='([0]="m" [1]="y" [2]=" " [3]="p" [4]="a" [5]="s" [6]="s" [7]="w" [8]="o" [9]="r" [10]="d")'
I have multiple arrays ( I limit it to 3 ) & first time using arrays
The length of the arrays are the same. They correspond to the same records
So array a, b and c values are listed below:
array a = 1 2 3 4 5
array b = a b c d e
array c = v w x y z
I need to print then content so the output is like this on each line
1 a v
2 b w
3 c x
4 d y
5 e z
Can you help?
Thanks
Here's a more bash-ful version (if you will):
#!/usr/bin/env bash
# initialize arrays
a=(1 2 3 4 5)
b=(a b c d e)
c=(v w x y z)
# count elements (assuming all arrays are the same size)
numElems=${#a[#]}
# loop over all elements
for (( i = 0; i < numElems; i++ )); do
# -e ensures that escape sequences such as \t are recognized
echo -e "${a[i]}\t${b[i]}\t${c[i]}"
done
This is how I worked it out, hopefully there is a better way. There are 3 arrays sample listed above, Each array has a list of values in it. Since they are of equal length. This is what can be done . The $'\t' puts a tab in between.
s=${#a[#]}
counter=0
echo $counter
while [[ $counter -lt $s ]];
do
echo ${a[$counter]} $'\t' ${b[$counter]} $'\t' ${c[$counter]}
counter=$(( $counter + 1 ))
done