Use bash script to read numbers - linux

Write a bash script that will read 10 integers from users and append the output to a file ‘XYZ’. You are not allowed to use the ‘read’ statement more than once in the script.
#! /bin/bash
for i in {0,1,2,3,4,5,6,7,8,9}
do
read "i"
echo "0,1,2,3,4,5,6,7,8,9" >> XYZ
done
I am a student just bengin to learn this, I feel it is difficult, could you give me some suggestions? I think this should have many problems. Thank you very much.

Let's see what you already have. Your for loop does 10 iterations of a read command, and read appears only once in the script. You also append (>>) your output to the file XYZ.
You shouldn't use the same variable for loop counter and reading the input, though. And the sequence could be shortened to {0..9}.
What you're still missing is a condition to check that the user input actually is an integer. And you're probably supposed to output the value you read, not the string "0,1,2,3,4,5,6,7,8,9".
On a more general note, you may find the following guides helpful with learning bash:
Bash Guide for Beginners
Advanced Bash Scripting Guide

#!/bin/bash
echo 'Input 10 integers separated by commas:'
read line
nums=`echo -n "$line" | sed "s/,/ /g"`
for i in $nums; do
echo "$i" >> XYZ
done
If you input 9,8,7,6,5,4,3,2,1,0, those numbers will be appended to the XYZ file, each one in a new line.

Read 10 (or less,or more) integers into an array, output not more than the first 10:
read -p '10 integers please: ' -a number
IFS=,
echo "${number[*]:0:10}" >> XYZ
Input:
1 2 3 4 5 6 7 8 9 0
Output, comma separated:
1,2,3,4,5,6,7,8,9,0

Related

Wordlist Generator in Bash

I am trying to create a wordlist consisting of the same password followed by a 4-digit numeric pin. The pin goes through every possible combination of 10,000 variations. The desired output should be like this:
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 1111
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 1112
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 1113
and so on.
I created a shell script that almost get this, but awk doesn't seem to like having a variable passed through it, and seems to just print out every combination when called. This is the shell script:
#!/bin/bash
# Creates 10,000 lines of the bandit24pass and every possible combination
# Of 4 digits pin
USER="UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ"
PASS=$( echo {1,2,3,4,5,6,7,8,9}{1,2,3,4,5,6,7,8,9}{1,2,3,4,5,6,7,8,9}{1,2,3,4,5,6,7,8,9} | awk '{print $I}' )
for I in {1..10000};
do
echo "$USER $PASS"
done
I though $I would translate to $1 for the first run of the loop, and increment upwards through each iteration. Any help would be greatly appreciated.
I though $I would translate to $1 for the first run of the loop, and increment upwards through each iteration.
No, command substitutions are expanded once; like, when you do foo=$(echo), foo is an empty line, not a reference to echo.
This whole task could be achieved by a single call to printf btw.
printf 'UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ %s\n' {1111..9999}
Tyr this
$echo $user
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ
$for i in {1000..9999}; do echo $user $i; done;

I would like to add 2 random numbers on the end of each username created from a file. How would I do this in bash?

!#/bin/bash
echo "which list of names would you like to add?"
read file
USER_LIST="(cut -d " " -f 1,2,3 $file --output-delimeter='.') "
echo "$USER_LIST | while read user; do echo "useradd "$user"";
done
using userlist.txt
james bond
ben afflack
john stewart
abdul rahim muhammad
CURRENT OUTPUT
james.bond
ben.afflack
john.stewart
abdul.rahim.muhammad
desired output
james.bond22
ben.afflack13
john.stewart11
abdul.rahim.muhammad83
What would be the easiest way to add the numbers to the end? I was looking at doing something along the lines of .$((RANDOM%10)).$((RANDOM%10))
any help is much appreciated. Thank you
You're on the right track with using $RANDOM, however its easier than you think. I was able to do it with the following:
user=james.bond
rand=${RANDOM:0:2}
if [ ${#rand} -lt 2 ]
then
rand=0$rand
fi
user=$user$rand
This sets user to james.bond23 (or some other 2 digit number). You just use parameter expansion to pick out the first two numbers generated by $RANDOM.
Refering to your question on how to implement this in a loop I have added a small snippet without using cut.
Assuming you have the file userlist.txt with the following content
james bond
ben afflack
john stewart
abdul rahim muhammad
In this file each name is seperated by a new line (\n).
The reading can be done with a single while loop. With the following quick approach you are able to print the desired the output:
#!/bin/bash
echo "which list of names would you like to add?"
# Read your file
read file
echo "Reading $file."
# Iterating trough each line of your text file.
while read p; do
# Accessing each element with $p: e. g. echo $p
# Apply a string manipulation on $p, add a
# random number at the end and print it out
echo ${p// /.}.${RANDOM:0:2}
done < $file # Your filename of your text file
The part ${p// /.} is called bash string manipulation. If you are interested in this, you can take a look at Shell-Parameter-Expansion. But it's not specified by POSIX. Not all Unix shells implement it.

Line from bash command output stored in variable as string

I'm trying to find a solution to a problem analog to this one:
#command_A
A_output_Line_1
A_output_Line_2
A_output_Line_3
#command_B
B_output_Line_1
B_output_Line_2
Now I need to compare A_output_Line_2 and B_output_Line_1 and echo "Correct" if they are equal and "Not Correct" otherwise.
I guess the easiest way to do this is to copy a line of output in some variable and then after executing the two commands, simply compare the variables and echo something.
This I need to implement in a bash script and any information on how to get certain line of output stored in a variable would help me put the pieces together.
Also, it would be cool if anyone can tell me not only how to copy/store a line, but probably just a word or sequence like : line 1, bytes 4-12, stored like string in a variable.
I am not a complete beginner but also not anywhere near advanced linux bash user. Thanks to any help in advance and sorry for bad english!
An easier way might be to use diff, no?
Something like:
command_A > command_A.output
command_B > command_B.output
diff command_A.output command_B.output
This will work for comparing multiple strings.
But, since you want to know about single lines (and words in the lines) here are some pointers:
# first line of output of command_A
command_A | head -n 1
The -n 1 option says only to use the first line (default is 10 I think)
# second line of output of command_A
command_A | head -n 2 | tail -n 1
that will take the first two lines of the output of command_A and then the last of those two lines. Happy times :)
You can now store this information in a variable:
export output_A=`command_A | head -n 2 | tail -n 1`
export output_B=`command_B | head -n 1`
And then compare it:
if [ "$output_A" == "$output_B" ]; then echo 'Correct'; else echo 'Not Correct'; fi
To just get parts of a string, try looking into cut or (for more powerful stuff) sed and awk.
Also, just learing a good general purpose scripting language like python or ruby (even perl) can go a long way with this kind of problem.
Use the IFS (internal field separator) to separate on newlines and store the outputs in an array.
#!/bin/bash
IFS='
'
array_a=( $(./a.sh) )
array_b=( $(./b.sh) )
if [ "${array_a[1]}" = "${array_b[0]}" ]; then
echo "CORRECT"
else
echo "INCORRECT"
fi

For i in loop with printf error

My script:
#!/bin/sh
for i in {1..3}
do
cp dummy.dat dummy/dummy.`printf "%04d%s_shp" ${i}`
done
and the
error: printf: 9: {1..3}: expected numeric value
If I type:
for i in 0 2 3
The script is working.
What is wrong with my script on the top? Or anyone a solution?
Your /bin/sh doesn't support {1..3} which is a bash extension. You can either:
Use #!/bin/bash to ensure the script is always run with bash.
Use $(seq 1 3) which is a POSIX-compliant replacement which will supposedly work with all shells.
printf "%04d%s_shp" ${i}
^ ^
1 2
printf expects two values.
The %04d means it wants a number (which will be given 4 spaces and padded with leading zeros), the %s means it expects to get a string value. You are only supplying one value, i, to printf
Only a guess, but did you mean perhaps just:
printf "%04d_shp" ${i}
i.e., without the s% ?
The literal {1..3} is not numeric. It has numbers in it, but the shell doesn't (necessarily) interpret it as a range in a for; you have to write it out in full (or use a while loop and some expression calculation).

how to update a file with info from standard input (keyboard) with shell script?

Basically what I have to do is this:
I have a file containing names of students and their partial grades:
(firstname lastname grade)
And what I have to do is update that file with their exam grades and their final grades:
(partial+exam)/2
The exam grades are introduced via the keyboard. So I have to echo a student's name and read his exam grade from the keyboard, and update his line within the file, then move on to the next one, and when I'm all done sort it after the final grade column.
I'm stuck at reading the exam grade from the keyboard. I've tried using some form of awk and sed but cant get it to work (cant get the info from the keyboard) and I'm not even sure if thats how it has to be done.
Please help.
ty in advance,
bando
edit:
(ty for editing, im a bit new to this)
input looks like this:
Tom Green 7
Jenny Patricks 6
Andrew Gibbs 3
Collin Matthews 10
it has to run from a script. while running it should put to standard output the first and last name of a student and ask for his grade. once given it edits the file to look like:
Tom Green 7 9 8
and then steps to the next student.
This script does something similar you want:
#!/bin/bash
# $1 input file
# $2 output file (or equal to $1 if ommitted)
if [ -z "$2" ]; then
OUTFILE=$1
else
OUTFILE=$2
fi
cat $1 | while read -u 0 FIRST LAST PART ; do
echo "firstname: '$FIRST'"
echo "lastname: '$LAST'"
echo "grade: '$PART'"
read -p "Exam grade: " -u 1 EXAM
#Edit
# was let FINAL=(PART+EXAM)/2
# should be:
FINAL=$(calc \($PART+$EXAM\)/2)
echo "$FIRST $LAST $PART $EXAM $FINAL" >> tmp
echo "final grade: '$FINAL'"
echo -e "-----------\n"
done
mv tmp $OUTFILE
But the shell arithmetic is integer only. For dividing you have two operators: / (integer division) and % (reminder). I think you should consider other language for the task like python or perl.
Edit:
You may want to use the calc command from the apcalc. See the corrected script above. You'll have to tweak the calc command options to prevent it from taking over STDIN. Sorry I have to leave you with that - I have no time right now.
cat > will read from keyboard to wherever you like - press ctrl+D to close input.
You can use the read command to get user input from the user in shell script. For example
read data
echo $data.

Resources