Pretty simple, I need to test a C program by inputting a large number of integers into it. To do this, for this particularly case, I need to run the program, then when it waits for user input (scanf("%d, integer)), I need to give it the integer from the loop I'm currently at.
right now I have
for i in {1..5};
do
(echo -n "$i" && ./a2 $i)
done
but it still just waits for user input, then after user input is given, prints the integer of the loop I'm on. I've tried a few examples from similar problems I've found on stack exchange and elsewhere but so far no luck. I haven't ever really needed to mess about with shell scripting before so it's probably something simple I'm doing backasswordsly but no one else has done wrong before.
Try this!
for i in `seq 1 1000`; do echo $i | ./a2; done
Your solution
echo -n "$i" && ./a2 $i
would pass $i as argument for a2 not input.
I think what you need is not usually done using shell script.
You can write a c code to generate your input, which in this case is numbers from 1-10000. Let that file be testGenerator.c. Then, run this on your terminal:
gcc testGenerator.c
./a.out >input
This will create a file, named input which will have numbers from 1 to 10000, which is of course the o/p of testGenerator.c.
Then, if your program, in which you want input is compiled into a2, as I can see, you can run it as:
./a2 <input >output
and you will get the required output in the file output. If you don't write >output here, you will see o/p on terminal.
Also, when you are running this script, you are actually running the a2 10000 times and giving a number as command line argument, which is very different from taking input from stdin which of course, scanf does.
for i in {1..1000}; do echo $i | ./a2; done
Related
I've been trying to read numeric input from the terminal in Bash (Two separate approaches. First is directly entering numbers into the CLI and second reading the numbers from a file) and saving it in an array, sorting the array and showing the result. (The original problem stated that the input is saved in an array and then sorted)
I don't know if it's better to save it in a file and sort the values in the file or directly the input from the terminal into the array and sorting it afterwards. I have searched for both methods.
Thank you.
P.S. I've read many sources and links but unfortunately I couldn't come across a solution. I've tried using loops and prompting the user in asking how many numbers they want to feed in as the input but it was doomed to failure.
Where does the input come from? Someone entering numbers, or a file, another process?
Either way, you seem to expect a finite number of inputs which then need sorting. Just pipe your inputs into sort -n (-n is for numeric sort). No need to use an intermediate array.
# Print some numbers on the console, pipe into sort.
cat <<-EOF | sort -n
1
3
2
EOF
If your inputs are coming from a file:
# Create FILE holding unsorted numbers.
$ cat <<-EOF > FILE
1
3
2
EOF
# Sort contents of FILE.
$ cat FILE | sort -n
1
2
3
If you could be more specific, it would be easier to help.
Would you try the following:
if [[ -t 0 ]]; then
# This line is executed when input from the terminal.
echo "Input a numeric value and enter then continue. Enter a blank line when done."
fi
while read -r n; do
[[ -z $n ]] && break # exits the loop if the input is empty
ary+=("$n")
done
sorted=($(sort -n < <(printf "%s\n" "${ary[#]}")))
printf "%s\n" "${sorted[#]}"
It accepts both user's input from the terminal and redirection from a file.
It expects the input to be a list of values separated by newlines.
When typing on the terminal, a user can complete the input by entering
a blank line or pressing Ctrl+D.
The array ary holds the values in the input order.
The array sorted holds the sorted result.
The script does not check the validity of the input values. It may be
better to examine if the input is a valid numeric value depending on the application.
Hope this helps.
I'm trying to integrate a cat command into a for loop with the cat reading the element '$currentccoutput' but it seems (I think) that cat is reading the line literally rather than understanding that it's an array element with the name of a txt file.
#create an array of text files
currentccoutputs=($currentccfolder'/'*.txt*)
#basic for loop until I can get my cat command working
for currentccoutput in "${currentccoutputs[#]}"; do
cat "$currentccoutput" | while read LINE; do
# I have .txt files with three numbers per line
# that I would like to read / use
IFS=' ' read C1 C2 threshold
if [ $C1 != $C2 ] && [ $threshold \> 0.2 ]; then
echo "Huzzah!!!! Progress at last"
fi
done < "$currrentccoutput" # I don't know what
# this backwards chevron
# does but other people
# have used it...
done
I've no doubt there are other imperfections with this snippet but I'm entirely new to creating scripts so I'm trying to keep things within the realms of what I know for now and hopefully sophisticated solutions will come later. (for now, I'm trying to get from island A to island B, where a few bits of wood and some hemp rope will be both understood and replicable. Whilst I appreciate advice on - and hope one day to build - a decent frigate, right now it might leave me somewhat confused).
I've never even used 'while' 'read' or 'LINE', I've pinched it from someone else's solution.
I have used the echo command to ensure it's not my paths that are wrong, just that I'm not using cat correctly.
The only problem with how you're using cat is that you're overriding it with a (much better) shell-builtin redirection. That fine -- in fact, it's preferable; you shouldn't use cat unless you absolutely must.[1]
What is a problem is that you're running read LINE and then read C1 C2 threshold after each other, both coming from the same source.
This means that you read the first line of each file into the variable LINE (which your code never looks at again), and the second line into the variables C1, C2 and threshold. If there are more lines, you read the third into LINE, the fourth into C1/C2/threshold, etc.
If you don't want to skip every other line (starting at the first one), just take out the read LINE entirely, making your code something like:
#!/usr/bin/env bash
case $BASH_VERSION in '') echo "ERROR: This script must be run with bash" >&2; exit 1;; esac
currentccoutputs=( "$currentccfolder"/*.txt )
for currentccoutput in "${currentccoutputs[#]}"; do
while IFS=$' \t\r' read -r c1 c2 threshold; do
if [ "$c1" != "$c2" ] && [ "$(bc -l <<<"$threshold > 0.2")" = 1 ]; then
echo "Huzzah!!!! Progress at last: c1=$c1; c2=$c2; threshold=$threshold"
fi
done < "$currentccoutput"
done
See:
BashFAQ #1 - How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
BashFAQ #22 - How can I calculate with floating point numbers instead of just integers? (describing the bc idiom used above)
BashFAQ #24 - I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read? (describing why cat | while read is a Bad Idea)
[1] - Yes, this means you should ignore many if not most of the examples of bash code you find online. Sturgeon's Law applies.
I have a C program that I want to run without having to manually type commands into. I have 4 commands (5 if you count the one to exit the program) that I want given to the program and I don't know where to start. I have seen some stuff like
./a.out <<<'name'
to pass in a single string but that doesn't quite work for me.
Other issues I have that make this more difficult are that one of the commands will give an output and that output needs to be a part of a later command. If I had access to the source code I could just brute force in some loops and counters so I am trying to get a hold of it but for now I am stuck working without it. I was thinking there was a way to do this with bash scripts but I don't know what that would be.
In simple cases, bash script is a possibility: run the executable in coproc (requires version 4). A short example:
#!/bin/bash
coproc ./parrot
echo aaa >&${COPROC[1]}
read result <&${COPROC[0]}
echo $result
echo exit >&${COPROC[1]}
with parrot (a test executable):
#!/bin/bash
while [ true ]; do
read var
if [ "$var" = "exit" ]; then exit 0; fi
echo $var
done
For a more serious scenarios, use expect.
First I should perhaps explain what I want to do...
I have 'n' amounts of files with 'n' amount of lines. All I know is
that the line count will be even.
The user selects the files that they want. This is saved into an
array called ${selected_sets[#]}.
The program will print to screen a randomly selected 'odd numbered'
line from a randomly selected file.
Once the line has been printed, I don't want it printed again...
Most of it is fine, but I am having trouble creating arrays based on the contents of ${selected_sets[#]}... I think I have got my syntax all wrong :)
for i in ${selected_sets[#]}
do
x=1
linecount=$(cat $desired_path/$i | wc -l) #get line count of every set
while [ $x -le $linecount ]
do ${i}[${#${i}[#]}]=$x
x=$(($x+2)) # only insert odd numbers up to max limit of linecount
done
done
The problem is ${i}[${#${i}[#]}]=$x
I know that I can use array[${#array[#]}]=$x but I don't know how to use a variable name.
Any ideas would be most welcome (I am really stumped)!!!
In general, this type is question is solved with eval. If you want a a variable named "foo" and have a variable bar="foo", you simply do:
eval $bar=5
Bash (or any sh) treats that as if you had typed
foo=5
So you may just need to write:
eval ${i}[\${#${i}[#]}]=$x
with suitable escapes. (A useful technique is to replace 'eval' with 'echo', run the script and examine the output and make sure it looks like what you want to be evaluated.)
You can create named variables using the declare command
declare -a name=${#${i}[#]}
I'm just not sure how you would then reference those variables, I don't have time to investigate that now.
Using an array:
declare -a myArray
for i in ${selected_sets[#]}
do
x=1
linecount=$(cat $desired_path/$i | wc -l) #get line count of every set
while [ $x -le $linecount ]
do
$myArray[${#${i}[#]}]=$x
let x=x+1 #This is a bit simpler!
done
done
Beware! I didn't test any of the above. HTH
I have a program written in C that operates similar to the below output.
WELCOME TO PROGRAM.
Hit 1 to do task 1.
Hit 2 to do task 2.
Hit q to quit.
What i need is a bash shell script that start the program, then enters 1, 2 and q into the program so i can test all the functionality in one command.
I would assume it to look similar to the following
#!/bin/bash
./start kernel
1
2
q
You can use a "here document" . The syntax looks like this:
./start kernel <<EOF
1
2
q
EOF
"EOF" can be whatever unique word you want, as long as it isn't something you'll actually need in the input.
Typically you use expect for testing these types of applications.
You can save your input in a text file - input.txt and execute your program this way: ./program < input.txt
I do this:
#! /bin/bash
printf "1\n2\nq\n" | ./start kernel
You can think of shell scripts as what they are... just each line being executed in an (albeit new) shell.
A simple way to do this sort of input is, assuming [your program] accepts stdin, is:
#!/bin/bash
echo "1" | [your program] > [logfile1]
echo "2" | [your program] > [logfile2]
echo "q" | [your program] > [logfileq]