Shell output to text file - bash

So, I have the following shell:
#!/bin/bash
for (( i = 1; i <= 6; i++ ))
do
printf in_port=$i,actions=
for (( j = 1 ; j <= 6; j++ ))
do
if [ $i != $j ]; then
printf output:$j,
fi
done
printf "\n"
done
Which, produces the following output:
home#mininet:~$ ./hostsScript.sh
in_port=1,actions=output:2,output:3,output:4,output:5,output:6,
in_port=2,actions=output:1,output:3,output:4,output:5,output:6,
in_port=3,actions=output:1,output:2,output:4,output:5,output:6,
in_port=4,actions=output:1,output:2,output:3,output:5,output:6,
in_port=5,actions=output:1,output:2,output:3,output:4,output:6,
in_port=6,actions=output:1,output:2,output:3,output:4,output:5,
How would I go about appending each line of this output to a txt file, line-by-line?

option 1 inside the script:
#!/bin/bash
for (( i = 1; i <= 6; i++ ))
do
printf in_port=$i,actions=
for (( j = 1 ; j <= 6; j++ ))
do
if [ $i != $j ]; then
printf output:$j,
fi
done
printf "\n"
done >> output_file
option 2 inside the script:
#!/bin/bash
exec >> output_file
for (( i = 1; i <= 6; i++ ))
do
printf in_port=$i,actions=
for (( j = 1 ; j <= 6; j++ ))
do
if [ $i != $j ]; then
printf output:$j,
fi
done
printf "\n"
done
option 3 in run command:
./hostsScript.sh >> output_file

Related

Ubuntu bash –eq: binary operator expected - nested for loop

I am trying to make Linux bash for my study homework and I think everything is fine(checked many resources), but still error is showing up (–eq: binary operator expected ). What's wrong in my example?
for (( i=1; i <= 3; i++)) ### Outer for loop ###
do
for (( j=1; j <= 3; j++)) ### Inner for loop ###
do
tot=$(expr $i + $j)
echo „tot value: $tot”
tmp=$(expr $tot % 2)
echo „tmp value: $tmp”
if [ $tmp –eq 0 ]; then
echo –e –n „\033[47m ”
else
echo –e –n „\033[40m”
fi
done
echo –e –n „\033[40m” #### set back background colour to black
echo „” #### print the new line ####
done
You are using the wrong character in –eq. It should be a minus (-), not a hyphen (–). The same goes for the hyphen you use on the echo lines.
Also consider using bash's built-in arithmetic expansion instead of expr and test:
#!/bin/bash
for (( i=1; i <= 3; i++)) ### Outer for loop ###
do
for (( j=1; j <= 3; j++)) ### Inner for loop ###
do
(( tot = i + j ))
echo "tot value: $tot"
(( tmp = tot % 2 ))
echo "tmp value: $tmp"
if (( tmp == 0 )); then
echo -e -n "\033[47m "
else
echo -e -n "\033[40m"
fi
done
echo -e "\033[40m" #### set back background colour to black
done

How to process value from for loop in shell

I have to a perform logic like this.
I have a array.
expression for this in shell
[(first no + arrlen) - ( index +1 ) - ge 10 ]
I have code this like this but it's not working
#!/bin/bash
array=(4 5 6 7 8 9)
for i in ${array[#]}
do
echo $i
done
echo "${#array[#]}"
l=${#array[#]}
count=0
for (( i=0; i < ${#array[#]}; i++ ))
do
if [ ($(`expr $i + $l`) - $(`expr ${!array[#]} + 1`)) -ge 10 ]
then
count=`expr $count + 1`
else
echo
fi
done
Your code could look like this:
#!/bin/bash
array=(4 5 6 7 8 9)
for i in "${array[#]}"; do
echo "$i"
done
length=${#array[#]}
first=${array[0]}
count=0
for (( i=0; i < length; i++ )); do
if (( (first + length) - (i + 1) >= 10 )); then
((count++))
else
echo "something"
fi
done
Don't use expr, use (( )) for arithmetic expressions
Quote expansions: "$i", "${array[#]}", ...
${!array[#]} expands to ALL indexes of your array, not the current index

How to use a command output as for loop condition in bash?

I wrote a for loop to work while a PID is running:
for (( j=0; (j < 40) && `kill -0 $pid` ; j++ )); do
printf "."
sleep 1
done
But it does not work and shows following error:
line 98: ((: (j < 40) && : syntax error: operand expected (error token is "&& ")
I tried other options such as:
for (( j=0; (j < 40) && (kill -0 $pid) ; j++ )); do
for (( j=0; ((j < 40)) && ((kill -0 $pid)) ; j++ )); do
for (( j=0; ( ((j < 40)) && ((kill -0 $pid)) ) ; j++ )); do
for (( j=0; [ ((j < 40)) && ((kill -0 $pid)) ] ; j++ )); do
for (( j=0; ((j < 40)) && [kill -0 $pid] ; j++ )); do
But all of above variations cause some errors.
You can't use command substitution with ` inside of the arithmetic evaluation context of ((...)). It is probably easiest to rewrite this as a while loop.
tries=0
while kill -0 $pid; do
(( tries++ > 40 )) && break
printf "."
sleep 1
done

Bash script - a puzzle

The script takes only one argument (call it n). It then alternately adds and subtracts each digit of the numbers from 1 through n.
For example:
n = 12
1 - 2 + 3 - 4 + 5 - 6 + 7 - 8 + 9 - 1 + 0 - 1 + 1 - 1 + 2
output: 5
#!/bin/bash
number=$1
result=1
if (( number == 1 || number == 0 )); then
echo
echo number: $number
echo
else
for (( i = 1; i < number; i++ )); do
if (( i < 10 )); then
if (( i % 2 == 0 )); then
let "result = result + i + 1"
else
let "result = result - i - 1"
fi
else
for (( i = 10; i <= number; i++ )); do
if (( i < 100 && i >= 10)); then
let "result = result - i/10 + i%10"
else
let "result = result - i/100 + (i%100)/10 - (i/100)%10"
fi
done
fi
done
echo
echo result: $result
echo number: $number
echo
fi
It works fine for ints 0 to 9, but for n>9 it gives the wrong answer.
Please correct my script and explain to me why it's behaving like this.
PS I'm new to bash scripting, so I'd love to see another solution to this puzzle
PPS I'm familiar to java
EDIT
I fixed the code, and it works correct now
#!/bin/bash
number=$1
result=1
if (( number == 1 || number == 0 )); then
echo
echo number: $number
echo
else
for (( i = 1; i < number; i++ )); do
if (( i < 9 )); then
if (( i % 2 == 0 )); then
let "result = result + i + 1"
else
let "result = result - i - 1"
fi
fi
done
for (( i = 10; i <= number; i++ )); do
if (( i < 100 )); then
let "result = result - i/10 + i%10"
else
if (( i % 2 == 0 )); then
let "result = result - i/100 + (i%100)/10 - (i%100)%10"
else
let "result = result + i/100 - (i%100)/10 + (i%100)%10"
fi
fi
done
echo
echo result: $result
echo number: $number
echo
fi
Ok this should work apologies that I miss-read the question earlier
number=$1
MATSTR="";
for((i=1; i <= number; i++)); do
MATSTR="$MATSTR$i";
done;
echo $MATSTR | sed -e 's/\(.\)\(.\)/\1-\2+/g' | sed 's/+$//' | bc
Explanation:
For loop to create string concatenating all numbers from 1 to the number.
sed statement replaces the every two digits with 1st digit minus second digit plus
sed removes any trailing plus
bc calculates the statement
Here's your original solution, but with bug fixes (in comments). It still won't work for number > 99, of course.
#!/bin/bash
number=$1
result=0 # Don't start at 1!!
if (( number == 1 || number == 0 )); then
echo
echo number: $number
echo
else
for (( i = 1; i <= number; i++ )); do # <=, not <
if (( i < 10 )); then # < 10, not < 9
if (( i % 2 == 0 )); then
let "result = result - i" # subtraction! Also, the +1 was unnecessary
else
let "result = result + i" # addition!
fi
else
if (( i < 100 && i >= 10)); then
let result=result-i/10+i%10
else
let "result=result-i/100+(i%100)/10-(i/100)%10"
fi
fi
done
echo
echo result: $result
echo number: $number
echo
fi
After misreading the question, (or the question being unclear), the answer took only minor adjustments. The sting solution is probably the simplest approach using modulo to togget +/-:
#!/bin/bash
declare -i num=$1
declare -i res=0
str=""
[ "$num" -gt 1 ] || {
printf "\n Error: invalid input. usage: %s int (greater than 1)\n\n" "${0//*\//}"
exit 1
}
for ((i = 1; i <= $num; i++)); do # create the string of digits
str="${str}${i}"
done
printf "\n Calculations:\n\n"
for ((i = 0; i < ${#str}; i++)); do # walk down the string adding/subtracting each digit
if [ $((i % 2)) -eq 0 ]; then
((res+=${str:$i:1}))
printf " res + %3s = %3s\n" "${str:$i:1}" "$res"
else
((res-=${str:$i:1}))
printf " res - %3s = %3s\n" "${str:$i:1}" "$res"
fi
done
printf "\n Final Result: %s\n\n" "$res"
exit 0
output:
$ ./puzzle.sh 12
Calculations:
res + 1 = 1
res - 2 = -1
res + 3 = 2
res - 4 = -2
res + 5 = 3
res - 6 = -3
res + 7 = 4
res - 8 = -4
res + 9 = 5
res - 1 = 4
res + 0 = 4
res - 1 = 3
res + 1 = 4
res - 1 = 3
res + 2 = 5
Final Result: 5

bash for with numerical comparison and file existence

I tried to do a for loop with 2 conditions but I didn't succeed in any way:
for (( i=0 ; -e /file && i < 10 ; i++ ))
of course I tried any combination of parentheses like:
for (( i=0 ; [ -e /file ] && [ i < 10 ] ; i++ ))
for (( i=0 ; [ -e /file -a i < 10 ] ; i++ ))
What's wrong on this?
I googled a lot for this, but I didn't find any suggestion.
You have to do some subshell trickery to pull this off:
for (( i=0 ; $([ -e /file -a $i -lt 10 ]; echo "$?") == 0; i++ ))
Or probably better:
for (( i=0 ; $([ -e /file ]; echo "$?") == 0 && i < 10; i++ ))
What's happening here is that $(...) is being run and placed into the mathematical expression ... == 0. When it's run the echo "$?" spits out the return code for [ which is 0 for no-error (i.e. expression is true), and 1 for error (i.e. expression is false) which then gets inserted as 0 == 0 or 1 == 0.

Resources