I need to upload this code, but the code is too large and confusing, can someone possibly help me to summarize this code or make it smaller? Its only the input part which's kinda confusing.
input(){
while read line;
do
for name in $line;
do
if [ "$name" == "`cat /etc/passwd | cut -f1 -d: | grep "^$name"`" ]
then
#echo $name----------
if [[ $s -eq 0 && $l -eq 0 && $i -eq 0 && $I -eq 0 && $u -eq 0 ]]; then
standard
fi
if [ $s -eq 1 ]
then
keepSudoUser
fi
if [ $l -eq 1 ]
then
interactiveShell
fi
if [ $i -eq 1 ]
then
userUnder1000
fi
if [ $I -eq 1 ]
then
userOver1000
fi
if [ $u -eq 1 ]
then
excludeUser
fi
fi
NO=0
done
done
}
input
This is more compact:
input() {
while read -ra names; do
for name in "${names[#]}"; do
if grep -q "^${name}:" /etc/passwd; then
[[ "$s$l$i$I$u" == "00000" ]] && standard
(( s == 1 )) && keepSudoUser
(( l == 1 )) && interactiveShell
(( i == 1 )) && userUnder1000
(( I == 1 )) && userOver1000
(( u == 1 )) && excludeUser
fi
NO=0
done
done
}
input
A more strict translation would be
((s == 0 && l == 0 && i == 0 && I == 0 && u == 0)) && standard
# or
(( !(s || l || i || I || u) )) && standard
Related
read X;
read Y;
read Z;
if [[ $X,$Y,$Z -ne "0" ]]; then
if [[ $X,$Y,$Z -ge 1 && $X,$Y,$Z -le 1000 ]] && [[ $((X+Y)) -gt $Z || $((Y+Z)) -gt $X || $((X+Z)) -gt $Y ]]; then
case $X,$Y,$Z in
$X -eq $Y && $Y -eq $Z && $X -eq $Z ) echo "EQUILATERAL";;
esac
else
echo "bye";
fi
fi
*./bashtesting.sh: line 7: syntax error near unexpected token `-eq
./bashtesting.sh: line 7: $X -eq $Y && $Y -eq $Z && $X -eq $Z ) echo "EQUILATERAL";;*
how to equate the three variables at a time?
This is how I would do it, with a loop and associative array.
#!/usr/bin/env bash
for h in x y z; do
read -rp 'Enter input: ' input
if [[ -z $input ]]; then
printf >&2 '%s is empty, please try again!\n' "${input:-input}"
exit 1
elif [[ $input != *[0-9]* ]]; then
printf '%s is not an int, please try again!\n' "$input"
exit 1
else
declare -A num[$h]=$input
fi
done
for i in "${num[#]}"; do
if ! (( i == 0 )); then
for j in "${num[#]}"; do
if (( j > 1 && j < 100 )); then
if (( (num[x] + num[y]) > num[z] || (num[y] + num[z]) > num[x] || (num[x] + num[z]) > num[y] )); then
if (( num[x] == num[y] && num[y] == num[x] && num[x] == num[z] )); then
echo equilateral
break 2
fi
fi
fi
done
fi
done
It it not pretty, It looks like an Anti Pattern, and there might be a better way to do it but this will get you there I suppose.
PROMPT_COMAND runs slow. Code optimization needed.
I use bash builtin PROMPT_COMMAND to customize PS1. Too much echo | grep commands were executed to get colorful git branch indication.The prompt runs much slower. Any ideas about optimazation?
function git_branch {
branch="`git branch 2>/dev/null | grep "^\*" | sed -e "s/^\*\ //"`"
if [ "${branch}" != "" ];then
if [ "${branch}" = "(no branch)" ];then
branch="(`git rev-parse --short HEAD`...)"
fi
echo "$branch"
fi
}
# display last two dentry
function get_curdir {
dir=$(pwd);
last_dirent=${dir##*/}
dir=${dir%/*}
lastbutone_dirent=${dir##*/}
echo -n "${lastbutone_dirent}/${last_dirent}"
}
# colours
RED="\[\033[1;31m\]"
GREEN="\[\033[1;32m\]"
BROWN="\[\033[0;33m\]"
BLUE="\[\033[1;34m\]"
PURPLE="\[\033[1;35m\]"
CYAN="\[\033[1;36m\]"
GRAY="\[\033[0;37m\]"
LIGHT_RED="\[\033[0;31m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_BLUE="\[\033[0;34m\]"
YELLOW="\[\033[1;33m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_GRAY="\[\033[0;37m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal's default colour
function prompt_command {
RET=$?
PS1="${CYAN}[${RESTORE}${GREEN}\u${RESTORE} "
PS1+="${BLUE}$(get_curdir)${RESTORE}${CYAN}]${RESTORE}"
BRANCH=$(git_branch)
if [ "${BRANCH}" != "" ]; then
STATUS="$(git status -s 2>/dev/null)"
if echo "${STATUS}" | grep -e "??"; then
PARENTHESES_COLOR=${RED}
else
PARENTHESES_COLOR=${GREEN}
fi >/dev/null
if [ "${STATUS}" = "" ]; then
BRANCH_COLOR=${GREEN}
else
if echo "${STATUS}" | grep -e "^[ M]M"; then
if echo "${STATUS}" | grep -e "^M[ M]"; then
BRANCH_COLOR=${PURPLE}
else
BRANCH_COLOR=${RED}
fi
elif echo "${STATUS}" | grep -e "^M "; then
BRANCH_COLOR=${YELLOW}
fi
fi >/dev/null
PS1+="${PARENTHESES_COLOR}(${RESTORE}${BRANCH_COLOR}$(git_branch)${RESTORE}${PARENTHESES_COLOR})${RESTORE}"
fi
if [ "$RET" = "0" ]; then
PS1+=" ${CYAN}->${RESTORE} "
else
PS1+=" ${RED}->${RESTORE} "
fi
}
export PROMPT_COMMAND=prompt_command
update
I run a simple test in some dir where a git repo resides and use time to get time cost.
for ((i=0;i<10000;i++));do
prompt_command;
done
Performance of the original version above is:
real 3m4.567s
user 1m32.698s
sys 3m2.495s
Then I change [] to [[ ]], diff like this:
17,18c17,18
< if [ "${branch}" != "" ];then
< if [ "${branch}" = "(no branch)" ];then
---
> if [[ "${branch}" != "" ]];then
> if [[ "${branch}" == "(no branch)" ]];then
58c58
< if [ "${BRANCH}" != "" ]; then
---
> if [[ "${BRANCH}" != "" ]]; then
65c65
< if [ "${STATUS}" = "" ]; then
---
> if [[ "${STATUS}" == "" ]]; then
81c81
< if [ "$RET" = "0" ]; then
---
> if [[ "$RET" == "0" ]]; then
Performance get a little worse
real 3m7.690s
user 1m30.717s
sys 3m6.676s
So, [] doesn't matter.
But builtin regex helps a lot.
When I changes to the following and replace $(pwd) with $PWD
if [ "${BRANCH}" != "" ]; then
regex_untracked=".*^\?\?.*"
regex_staged=".*^M[ M].*"
regex_modified=".*^[ M]M.*"
STATUS="$(git status -s 2>/dev/null)"
if [[ ${STATUS} =~ $regex_untracked ]]; then
PARENTHESES_COLOR=${RED}
else
PARENTHESES_COLOR=${GREEN}
fi >/dev/null
if [[ ${STATUS} =~ $regex_modified ]]; then
if [[ ${STATUS} =~ $regex_staged ]]; then
BRANCH_COLOR=${PURPLE}
else
BRANCH_COLOR=${RED}
fi
elif [[ ${STATUS} =~ $regex_staged ]]; then
BRANCH_COLOR=${YELLOW}
else
BRANCH_COLOR=${GREEN}
fi >/dev/null
PS1+="${PARENTHESES_COLOR}(${RESTORE}${BRANCH_COLOR}$(git_branch)${RESTORE}${PARENTHESES_COLOR})${RESTORE}"
fi
Time consumed decreases:
real 2m15.534s
user 1m1.036s
sys 2m15.043s
By the way, without this colorful branch feature, performance is
real 1m0.478s
user 0m29.499s
sys 1m1.411s
bash has its own built-in regular expression matching. For example, replace
echo "${STATUS}" | grep -e "^[ M]M"
with
regex="^[ M]M"
[[ $STATUS =~ $regex ]]
I am trying to write a bash script to find if a number is prime, but i can't find what is wrong with my script
#!/bin/bash
#set -x
echo -n "enter a number "
read isPrime
count=2
x=0
while [ $count -lt $isPrime ]; do
if [ `expr $isPrime % $count`-eq 0 ]; then
echo "not prime"
fi
count=`expr $count + 1`
done
echo " it is prime"
#set +x
Using factor would be easy. But if you somehow need a script, I would implement something like following. I'm not sure whether this is the best algorithm, but this is way efficient than yours.
function is_prime(){
if [[ $1 -eq 2 ]] || [[ $1 -eq 3 ]]; then
return 1 # prime
fi
if [[ $(($1 % 2)) -eq 0 ]] || [[ $(($1 % 3)) -eq 0 ]]; then
return 0 # not a prime
fi
i=5; w=2
while [[ $((i * i)) -le $1 ]]; do
if [[ $(($1 % i)) -eq 0 ]]; then
return 0 # not a prime
fi
i=$((i + w))
w=$((6 - w))
done
return 1 # prime
}
# sample usage
is_prime 7
if [[ $? -eq 0 ]]; then
echo "not a prime"
else
echo "it's a prime"
fi
You can find an explanation about the used algorithm here
Simple arithmetic expression enclosed in '((' evaluates to true when inside compound conditional expression '[['
HAVE_SRC=1
[[ (( $HAVE_SRC == 1 )) && -d $( pwd ) ]]
echo $? # returns 0 => true
HAVE_SRC=0
[[ (( $HAVE_SRC == 1 )) && -d $( pwd ) ]]
echo $? # returns 1 => false
HAVE_SRC=1
[[ (( $HAVE_SRC )) && -d $( pwd ) ]]
echo $? # returns 0 => true
PROBLEM:
HAVE_SRC=0
[[ (( $HAVE_SRC )) && -d $( pwd ) ]]
echo $? # returns 0 => true ????
Do not use (( ... )) inside of [[ ... ]]:
(( HAVE_SRC == 1 )) && [[ -d $pwd ]]
To see how bash interprets the expressions you gave, try running them with
set -xv
In shell script how can we compare (integer and floating point) ,(flaoting point and floating point),(floating point and integer),(integer and integer) with only one if condition.
i have few examples like
set X=3.1
set Y=4.1
if [ $X < $Y ] then
echo "wassup"
endif
But running the above from cron job doesnt seem to work.
The way to carry out floating point operations in bash is to use bc which is available on almost all linux distributions.
# bc will return 0 for false and 1 for true
if [ $(echo "23.3 > 7.3" | bc) -ne 0 ]
then
echo "wassup"
fi
There's a good article available on linux journal about floating point math in bash using bc.
Bah itself only handles integers. Use bc:
echo "$X>$Y" | bc
0
echo "$X<$Y" | bc
1
You don't need to worry about scale. It is just for the preocision of output formats:
X=3.000001
Y=3.0001
echo "$X>$Y" | bc
0
echo "$X<$Y" | bc
1
echo "scale=1;$X<$Y" | bc
1
below example works on bash shell.
X=3.1
Y=4.1
if [ $X -le $Y ]
then
echo "wassup"
fi
you may want to learn shell script here
EDIT. based on the comments to this answer (thanks to user unknown and glenn jackman), it seems that when using bc for a true/false test, the required bash test is simply:
(( $(echo "$X < $Y" |bc) )) ... see the test results and script below
wheras, the comparison to -ne 0 is needed for the old style bash [ ] test.
bash does not natively handle floating point numbers, but you can call a utility such as bc
From man bc - An arbitrary precision calculator language
X=3.1
Y=4.1
# This test has two superfluous components.
# See EDIT (above) and TESTS below
if (($(echo "scale=9; $X < $Y" |bc)!=0)) ;then
echo "wassup"
fi
TEST results:
if [ "1" ] true
[ "1" ] true
if [ "0" ] true
[ "0" ] true
if [ 1 ] true
[ 1 ] true
if [ 0 ] true
[ 0 ] true
if (( "1" )) true
(( "1" )) true
if (( "0" )) false
(( "0" )) false
if (( 1 )) true
(( 1 )) true
if (( 0 )) false
(( 0 )) false
echo "1<1"|bc true
echo "1<0"|bc true
TEST script:
printf 'if [ "1" ] '; if [ "1" ]; then echo true; else echo false; fi
printf ' [ "1" ] '; [ "1" ] && echo true || echo false
printf 'if [ "0" ] '; if [ "0" ]; then echo true; else echo false; fi
printf ' [ "0" ] '; [ "0" ] && echo true || echo false
echo
printf 'if [ 1 ] '; if [ 1 ]; then echo true; else echo false; fi
printf ' [ 1 ] '; [ 1 ] && echo true || echo false
printf 'if [ 0 ] '; if [ 0 ]; then echo true; else echo false; fi
printf ' [ 0 ] '; [ 0 ] && echo true || echo false
echo
printf 'if (( "1" )) '; if (("1")); then echo true; else echo false; fi
printf ' (( "1" )) '; (("1")) && echo true || echo false
printf 'if (( "0" )) '; if (("0")); then echo true; else echo false; fi
printf ' (( "0" )) '; (("0")) && echo true || echo false
echo
printf 'if (( 1 )) '; if (( 1 )); then echo true; else echo false; fi
printf ' (( 1 )) '; (( 1 )) && echo true || echo false
printf 'if (( 0 )) '; if (( 0 )); then echo true; else echo false; fi
printf ' (( 0 )) '; (( 0 )) && echo true || echo false
echo
printf 'echo "1<1"|bc '; echo "1<1"|bc >/dev/null && echo true || echo false
printf 'echo "1<0"|bc '; echo "1<0"|bc >/dev/null && echo true || echo false