И здравствуйте!
Продолжаю пытаться изучать Bash и есть такое задание.
При запуске надо ввести два числа.
Если 1-е больше 2-го, то они складываются. Если нет — сообщение «Ошибка».
Скрипт я написал и он работает. Вот его содержание:
#!/bin/bash
read -p "Введите 1-е число:" A
echo "$A"
read -p "Введите 2-е число:" B
echo "$B"
if [[ $A -gt $B ]]; then
echo "Результат" $(($A+$B));
else
echo "Error"
fi
Но я хочу в начале задать переменную по типу C=$(($A+$B)) и тут получается фигня при запуске скрипта строка 2: +: синтаксическая ошибка: ожидается операнд (неверный маркер «+»)
#!/bin/bash
C=$(($A+$B))
read -p "Введите 1-е число:" A
echo "$A"
read -p "Введите 2-е число:" B
echo "$B"
if [[ $A -gt $B ]]; then
echo "Результат" $C;
else
echo "Error"
fi
Если же я убираю $ у А и В C=$((A+B)), то ошибки нет, но результат выдает 0 
Где я ошибся?
задан 13 янв в 8:45
KradKrad
112 бронзовых знака
2
Складываете переменные до ввода их значений
ответ дан 13 янв в 8:53
OopssOopss
7665 серебряных знаков9 бронзовых знаков
1
Вы пытаетесь выполнить фрифметическое действие с незаданными переменными. Строка C=$(($A+$B)) преобразуется в C=$((+)) т.к. $A и $B еще не заданы в результате ошибка:
bash: +: синтаксическая ошибка: ожидается операнд (неверный маркер «+»)
Баш допускает обозначение переменных в арифметических выражениях без $ в этом случае он ищет переменную с указанным именем и использует её значение для выполнения арифм. действия, если переменная не задана автоматически подставляется 0. Поэтому конструкция C=$((A+B)) работает т.к. фактически получается C=$((0+0)). Но естественно для выполнения искомой задачи(сложить А и B) это не подходит.
ответ дан 13 янв в 9:17
IvanIvan
4613 серебряных знака7 бронзовых знаков
1
tl;dr:
Double-quote your command substitution:
let initialLines="$(grep '' "$1" | wc -l || true)"
That said, as explained in chepner’s helpful answer, you could just use a simple assignment without needing to double-quote the RHS, although to get the same outcome as with let here, be sure to declare the variable with -i first; e.g., declare -i initialLines
It looks like the RHS of your assignment — the command substitution ($(...)) — evaluates either to the empty string or a whitespace-prefixed string in the course of the shell expansions that happen before the command is executed, so that bash ends up trying to parse one of the following commands:
let initialLines=
let initialLines= 2
If you try these in isolation, you’ll get the syntax error you’ve experienced.
The most likely explanation is that you’re using BSD wc, such as on macOS, which outputs the line count requested with -l with leading whitespace.
A simple fix is to double-quote the command substitution:
let initialLines="$(grep '' "$1" | wc -l || true)"
As for the command in your command substitution (it may just be an example, but it’s worth commenting on):
-
grep ''will always return all input lines, so it’s nothing more than a less efficientcat. -
There is no point in using
|| true:-
The exit code of the subshell in which the command substitution runs is not relevant, even with
set -ein effect. -
Also, by using
trueas the alternative command, you’ll break theletcommand as well, because builtintruehas no stdout output.
-
-
In summary, your entire command substitution could be reduced to
wc -l < "$1".
I am getting this error bellow:
Path to the shell file:line 6: ++++: syntax error: operand expected (error token is "+")
and
Path to the shell file:line 13: ((: i <= : syntax error: operand expected (error token is "<= ")
This is my script:
#!/bin/bash
SCRIPTPATH=$( cd $(dirname $0) ; pwd -P )
file="$SCRIPTPATH/android/sdcard.img"
file2="$SCRIPTPATH/android/devices.txt"
TOTALDEVICES=$(($1+$2+$3+$4+$5))
ANDROID4=0
ANDROID5=0
ANDROID5_1=0
ANDROID6=0
ANDROID7=0
echo $TOTALDEVICES
for ((i = 1; i <= $TOTALDEVICES; i++));
do
if (($1 > 0 && $ANDROID4 < $1))
then
echo "Device$i PACKAGE(avd4.4) 1"
ANDROID4=$((ANDROID4 + 1))
echo "no" |~/Android/Sdk/tools/bin/avdmanager create avd -f --package 'system-images;android-19;google_apis;armeabi-v7a' --name "avd4" --tag 'google_apis' -p $SCRIPTPATH/android/avd4
fi
if (($2 > 0 && $ANDROID5 < $2 && $ANDROID4 == $1 && $i > $ANDROID4))
then
echo "Device$i PACKAGE(avd5.0) 2"
ANDROID5=$((ANDROID5 + 1))
echo "no" |~/Android/Sdk/tools/bin/avdmanager create avd -f --package 'system-images;android-21;google_apis;armeabi-v7a' --name "avd5" --tag 'google_apis' -p $SCRIPTPATH/android/avd5
fi
if (($3 > 0 && $ANDROID5_1 < $3 && $ANDROID5 == $2 && $i > $ANDROID5 + $ANDROID4))
then
echo "Device$i PACKAGE(avd5.1) 3"
ANDROID5_1=$((ANDROID5_1 + 1))
echo "no" |~/Android/Sdk/tools/bin/avdmanager create avd -f --package 'system-images;android-22;google_apis;x86' --name "avd5.1" --tag 'google_apis' -p $SCRIPTPATH/android/avd5.1
fi
if (($4 > 0 && $ANDROID6 < $4 && $ANDROID5_1 == $3 && $i > $ANDROID5_1 + $ANDROID5 + $ANDROID4))
then
echo "Device$i PACKAGE(avd6) 4"
ANDROID6=$((ANDROID6 + 1))
echo "no" | ~/Android/Sdk/tools/bin/avdmanager create avd -f --package 'system-images;android-23;google_apis;x86' --name "avd6" --tag 'google_apis' -p $SCRIPTPATH/android/avd6
fi
if (($5 > 0 && $ANDROID7 < $5 && $ANDROID6 == $4 && $i > $ANDROID6 + $ANDROID5_1 + $ANDROID5 + $ANDROID4))
then
echo "Device$i PACKAGE(avd7) 5"
ANDROID7=$((ANDROID7 + 1))
echo "no" | ~/Android/Sdk/tools/bin/avdmanager create avd -f --package 'system-images;android-24;google_apis;x86' --name "avd7" --tag 'google_apis' -p $SCRIPTPATH/android/avd7
fi
done
AVDMANAGEROUTPUT=$(~/Android/Sdk/tools/bin/avdmanager list avds | grep "Name:")
AVDMANAGEROUTPUT=${AVDMANAGEROUTPUT//$'n'/} # Remove all newlines.
AVDMANAGEROUTPUT=${AVDMANAGEROUTPUT%$'n'} # Remove a trailing newline.
DEVICES=()
i=0
IFS=' ' read -r -a array <<< "$AVDMANAGEROUTPUT"
for index in "${!array[@]}"
do
rem=$(( $index % 2 )) #check for odd number to avoid Name:
if [ $rem -eq 1 ]
then
echo "${array[index]}" #Now put values into an array
DEVICES[$i]=`echo @"${array[index]}"`
i=$((i+1))
fi
done
# Check if the sdcard is available
if [ -f "$file" ]
then
echo "$file found."
~/Android/Sdk/emulator/emulator ${DEVICES[0]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[1]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[2]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[3]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[4]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
sleep 110
else
# if there is none,here we are creating one
echo "$file not found."
~/Android/Sdk/emulator/mksdcard 10G "$SCRIPTPATH/android/sdcard.img"
sleep 5
~/Android/Sdk/emulator/emulator ${DEVICES[0]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 &
~/Android/Sdk/emulator/emulator ${DEVICES[1]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[2]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[3]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
~/Android/Sdk/emulator/emulator ${DEVICES[4]} -sdcard $file >> "$SCRIPTPATH/emulators.txt" 2>&1 & #open the emulator
sleep 110
fi
![]()
Zanna♦
69k56 gold badges215 silver badges327 bronze badges
asked May 4, 2017 at 6:41
1
Line 6 of your script expects arguments 1 to 5 to exist. If you run your script with no arguments $1+$2+$3+$4+$5 will become +++++ which explains the error message. (A similar explanation is valid for the second error message.) Perhaps you should check that 5 arguments have been provided and exit with an error message if this test fails, e. g.:
if [ $# != 5 ]
then
echo "Usage: scriptname num1 num2 num3 num4 num5"
exit 2
fi
Alternatively you can provide a default value for missing arguments with Bash’s parameter expansion. In the following expression the first 5 command-line arguments, or 0 in their absence, are added to a sum:
$((${1-0} + ${2-0} + ${3-0} + ${4-0} + ${5-0}))
Note that you should also check that each of the 5 arguments is numeric before attempting to obtain their sum.
![]()
answered May 4, 2017 at 9:00
![]()
Thank you for your answer, you helped me see what I did wrong.
How did I fix it:
I then ran the sh file like ‘file.sh’ 1 1 1 1 1 which had enabled the emulators to run. The 1s determine how many emulators of each do I want to run.
answered May 9, 2017 at 13:51
0
The error message is caused by the line a=$(($ex / $f)), because there is no operand following the / (divide) operator. So the immediate suspicion is that the variable f is an empty string.
The cause of that is the behaviour of the $( ) command substitution when f is assigned. This collects the contents of stdout when the enclosed command pipeline is executed. As your factorial() function writes nothing to stdout, the value assigned to f is empty. The solution is to echo or print the value, in place of the return — e.g. as printf '%sn' "${fact}".
Some additional notes that might be helpful:
The value in the return statement represents the status of the function, not any data it may have produced. In the absence of a return statement, the exit status of the last command executed in the function is passed back to the caller.
The return status is truncated to 8 bits, and is unsigned, so it can only take the range 0-255.
In addition, the status of external commands has further conventions. Processes terminated by a signal get a status of 128 + the signal number. If the shell fails to create a new process, or to execute the command, 126 or 127 may be returned. Status 0 is conventionally success, and any small integer from 1 up indicates a command-detected error or unusual result. I would consider it wise to follow the same conventions in my shell functions, and never to return a data value this way.
Shell arithmetic is (according to the GNU/bash manual) evaluated in fixed-width integers. On my system, that appears to be 64-bit signed integers, but it may vary across systems and distros. 31 bits is only sufficient to hold 12!, and 63 bits only holds 20!, which may limit your scope.
This fragment shows Bash arithmetic overflowing 63 bits, somewhere around 9.22e+18.
Paul--) for k in {1..10}; do
> printf '%s %sn' $k $(( 3000000000000000000 * k ))
> done
1 3000000000000000000
2 6000000000000000000
3 9000000000000000000
4 -6446744073709551616
5 -3446744073709551616
6 -446744073709551616
7 2553255926290448384
8 5553255926290448384
9 8553255926290448384
10 -6893488147419103232
Paul--)
My go-to for large numbers is the dc command, which does unconstrained numeric size, but requires RPN (reverse polish notation). This fragment generates the RPN commands to list factorials up to 10!
Paul--) { echo 1; seq -s ' p * p ' 2 10; echo ' p * p q'; }
1
2 p * p 3 p * p 4 p * p 5 p * p 6 p * p 7 p * p 8 p * p 9 p * p 10
p * p q
Paul--)
and this is the execution (but I tested up to 400!):
Paul--) { echo 1; seq -s ' p * p ' 2 10; echo ' p * p q'; } | dc
2
2
3
6
4
24
5
120
6
720
7
5040
8
40320
9
362880
10
3628800
Paul--)
Answer by Greta Schaefer
Stack Overflow for Teams
Where developers & technologists share private knowledge with coworkers
,
Well, either way is correct. You can do whichever one you choose. And this should read the numbers and it should divide them up. It reads the numbers all at once, delimited by spaces, and they are already separated when read.
– Blue Ice
Nov 24 ’13 at 17:53
,Making statements based on opinion; back them up with references or personal experience.,Connect and share knowledge within a single location that is structured and easy to search.
Combination of ceving and Tomek’s:
#!/bin/bash
read num1 num2 num3
while [ $num1 -lt $num3 ]
do
echo $num1
num1=$((num1+num2))
done
Answer by Rodney Francis
Thanks for contributing an answer to Unix & Linux Stack Exchange!,Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.,
Stack Exchange network consists of 178 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.
,Making statements based on opinion; back them up with references or personal experience.
This fragment shows Bash arithmetic overflowing 63 bits, somewhere around 9.22e+18.
Paul--) for k in {1..10}; do
> printf '%s %sn' $k $(( 3000000000000000000 * k ))
> done
1 3000000000000000000
2 6000000000000000000
3 9000000000000000000
4 -6446744073709551616
5 -3446744073709551616
6 -446744073709551616
7 2553255926290448384
8 5553255926290448384
9 8553255926290448384
10 -6893488147419103232
Paul--)
My go-to for large numbers is the dc command, which does unconstrained numeric size, but requires RPN (reverse polish notation). This fragment generates the RPN commands to list factorials up to 10!
Paul--) { echo 1; seq -s ' p * p ' 2 10; echo ' p * p q'; }
1
2 p * p 3 p * p 4 p * p 5 p * p 6 p * p 7 p * p 8 p * p 9 p * p 10
p * p q
Paul--)
and this is the execution (but I tested up to 400!):
Paul--) { echo 1; seq -s ' p * p ' 2 10; echo ' p * p q'; } | dc
2
2
3
6
4
24
5
120
6
720
7
5040
8
40320
9
362880
10
3628800
Paul--)
Answer by Trenton English
#!/bin/sh
#
# script to see if the given value is correct
#
# Define errors
ER_AF=86 # Var is higher than five
ER_BO=87 # Var is below one
# Constants
a=5
b=1
# Execute sio and
# give var the output value of sio
var="$(/disk/sio -p3 -b57600 -R)"
echo $var
echo
# Test if var is above 5
if (( "$var" > "$a" ));
then
echo "test failed" # Var is higher than 5
exit $ER_AF
else
# Test if var is below 1
if (( "$var" < "$b" ));
then
echo "test failed" # var is below 1
exit $ER_BO
else
echo "test succes" # var is between 1 & 5
fi
fi
Answer by Barrett Jenkins
Line 6 of your script expects arguments 1 to 5 to exist. If you run your script with no arguments $1+$2+$3+$4+$5 will become +++++ which explains the error message. (A similar explanation is valid for the second error message.) Perhaps you should check that 5 arguments have been provided and exit with an error message if this test fails, e. g.:,Note that you should also check that each of the 5 arguments is numeric before attempting to obtain their sum.,To subscribe to this RSS feed, copy and paste this URL into your RSS reader.,
Swap every two elements in a list
Line 6 of your script expects arguments 1 to 5 to exist. If you run your script with no arguments $1+$2+$3+$4+$5 will become +++++ which explains the error message. (A similar explanation is valid for the second error message.) Perhaps you should check that 5 arguments have been provided and exit with an error message if this test fails, e. g.:
if [ $# != 5 ]
then
echo "Usage: scriptname num1 num2 num3 num4 num5"
exit 2
fi
Alternatively you can provide a default value for missing arguments with Bash’s parameter expansion. In the following expression the first 5 command-line arguments, or 0 in their absence, are added to a sum:
$((${1-0} + ${2-0} + ${3-0} + ${4-0} + ${5-0}))
Answer by Cruz Adkins
Find more questions by tags LinuxbashSSH,1Can browser-sync to be the reason for not setting the cookie?,3When you click on the name of the tab, the contents tab opens, but the entire unit jumps to the top of the viewport, how to fix?
#!/bin/bash
echo "Enter your name:"
read user_name
let count = `grep $user_name /etc/passwd | wc-l`
if [ $count -gt 0 ];
then
echo "In /etc/passwd file was found $count matches!"
else
echo "No match!"
fi
Answer by Waylon Merritt
NOTE: CalcFileSize is a calculated number. Not sure if that matters with this issue though. If so, here is that calculation.,The ‘if’ then works with that true/false result of the ((.,Here is the part of the code that this is referring to:,Write your ‘if’ test like this:
For some reason I am getting this error.
./watch-incoming.sh: line 47: [[: .68: syntax error: operand expected (error token is ".68")
Here is the part of the code that this is referring to:
CalcFileSize=.68 # Calculated field (see code below if needed)
FileSizeCheck=1.20
echo "Calculated File Size (GB): $CalcFileSize"
echo "File Size Check: $FileSizeCheck"
if [[ "$CalcFileSize" -ge "$FileSizeCheck" ]]; then
echo "Large"
else
echo "Small"
fi
Here is the output:
Calculated File Size (GB): .68
File Size Check: 1.20
./watch-incoming.sh: line 47: [[: .68: syntax error: operand expected (error token is ".68")
Small
NOTE: CalcFileSize is a calculated number. Not sure if that matters with this issue though. If so, here is that calculation.
CalcFileSize=$(echo "scale=2;$FileSizeBytes/$Byte" | bc -l)
Answer by Elliot Santana
line 12: 0++: syntax error: operand expected (error token is «+»),./asmt6: line 12: ((: 0++: syntax error: operand expected (error token is «+»),OK, so I need some help from someone more familiar with coding. I need a script file that would take in the input (parameters) and count how many letters are in each one., each argument you leave after your bash command will be captured as #$ so lets say your command is called checkit.shso you run your script./checkit.sh one two three fouryou would have the following variables created and filled1$ ‘one’2$ ‘two’3$ ‘three’4$ ‘four’now you can count the letters in each variable (ill let you play with that one — i think lc might count letters)
#!/bin/bash
for var in "$@"; do
#echo "${#var}"
(( Letters[${#var}]++ ))
#echo ${Letters[${#var}]}
done
for i in ${!Letters[*]}; do
echo $i " letters: " ${Letters[$i]}
done
Answer by Frida Huffman
In this script for monitoring the real-time network port rate, there is an error on lines 21 and 22:,Shell script execution error [: 0: unary operator expected,If conditional statement in Bash reports an error [: missing `] ‘,Sometimes ora-04062 error occurs when database is running stored procedure
In this script for monitoring the real-time network port rate, there is an error on lines 21 and 22:
#!/bin/bash
#Modified by [email protected]
echo ===DTmobile NetSpeedMonitor===
sleep 1
echo loading...
sleep 1
ethn=$1
while true
do
RXpre=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $2}')
TXpre=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $10}')
sleep 1
RXnext=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $2}')
TXnext=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $10}')
clear
echo -e "ttt RX tt TX ttt TIME"
RX=$((${RXnext}-${RXpre}))
TX=$((${TXnext}-${TXpre}))
if [ $RX -lt 1024 ];then
RX="${RX}B/s"
elif [ $RX -gt 1048576 ];then
RX=$(echo $RX | awk '{print $1/1048576 "MB/s"}')
else
RX=$(echo $RX | awk '{print $1/1024 "KB/s"}')
fi
if [ $TX -lt 1024 ];then
TX="${TX}B/s"
elif [[ $TX -gt 1048576 ]];then
TX=$(echo $TX | awk '{print $1/1048576 "MB/s"}')
else
TX=$(echo $TX | awk '{print $1/1024 "KB/s"}')
fi
echo -e "$ethn t $RX $TX ttt `date +%k:%M:%S` "
done
Revised document
#!/bin/bash
#Modified by [email protected]
echo ===DTmobile NetSpeedMonitor===
sleep 1
echo loading...
sleep 1
ethn=$1
while true
do
RXpre=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $2}')
TXpre=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $10}')
sleep 1
RXnext=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $2}')
TXnext=$(cat /proc/net/dev | grep $ethn | sed 's/:/ /g' | awk '{print $10}')
clear
echo -e "ttt RX tt TX ttt TIME"
RX=$((RXnext-RXpre))
TX=$((TXnext-TXpre))
if [ $RX -lt 1024 ];then
RX="${RX}B/s"
elif [ $RX -gt 1048576 ];then
RX=$(echo $RX | awk '{print $1/1048576 "MB/s"}')
else
RX=$(echo $RX | awk '{print $1/1024 "KB/s"}')
fi
if [ $TX -lt 1024 ];then
TX="${TX}B/s"
elif [[ $TX -gt 1048576 ]];then
TX=$(echo $TX | awk '{print $1/1048576 "MB/s"}')
else
TX=$(echo $TX | awk '{print $1/1024 "KB/s"}')
fi
echo -e "$ethn t $RX $TX ttt `date +%k:%M:%S` "
done
The reason is that when the value of $is taken, only variables need to be followed in the brackets (variables can be calculated by themselves), and it is not necessary to take the value of variables in the brackets
RX=$((${RXnext}-${RXpre}))
TX=$((${TXnext}-${TXpre}))
change to:
RX=$((RXnext-RXpre))
TX=$((TXnext-TXpre))
