简体   繁体   中英

Consolidating Bash Script With If / Then / Else Statement

I'm somewhat new to the world of Bash scripting, and am still attempting to understand what most would consider to be the basics. I found this helpful guide which I have been pulling most of my information from, and despite it referring to "advanced" it actually covers the basics very well for a newcomer like myself.

At this point, I have written a script that works how I want it to, however I guess I'm what some might consider to be code conscious. So while my script does indeed work, I don't think I'm utilizing Bash's if/then/else statements properly.

Here is the small script I've written that basically checks for usernames, and whether or not they exist, via an API query. It allows a user to define a list via ./script.sh list , or if they do not define a list it simply attempts all variations of letters ( {a..z} ):

#!/bin/bash

# variables
host='https://api.example.com/api/users/'
sleep=1

# check if jq install
if ! jq_loc="$(type -p "jq")" || [ -z "$jq_loc" ]; then
  echo "no jq installed."
  sleep 1
  echo "we're going to install it now."
  sleep 2
  sudo apt-get install jq
fi

# specified list
if [ -n "$1" ] ; then
  list=`cat $1`
  for username in $list
  do
     #echo $username
     sleep $sleep
     VAL=`curl -s "$host$username" | jq -r ".id" | grep null`
     #echo $VAL
     if [[ $VAL == null ]]
     then
       echo -e "$username is available"
       echo "$username" >> username.free
     else
       echo -e "$username is taken"
     fi
  done
fi

# no list specified
if [ $# -eq 0 ] ; then
list=`echo {a..z}{a..z}{a..z}`
  for username in $list
  do
     #echo $username
     sleep $sleep
     VAL=`curl -s "$host$username" | jq -r ".id" | grep null`
     #echo $VAL
     if [[ $VAL == null ]]
     then
       echo -e "$username is available"
       echo "$username" >> username.free
     else
       echo -e "$username is taken"
     fi
  done
fi

As I stated, the script works exactly how I want it to. But where my concern comes in at is if [ $# -eq 0 ] ; then if [ $# -eq 0 ] ; then and if [ -n "$1" ] ; then if [ -n "$1" ] ; then . I feel like I'm echoing for it to do the same function needlessly. For example, instead of having to tell it to perform the curl command in each if , is there a way I can consolidate these two if 's into a single one?

Hopefully I have explained this well enough, and if not please just comment and I can update this question accordingly.

Thanks in advance!

Your if statements cover all logical branches. Thus, the following code block will be executed either way. So there is no reason to duplicate it. Simply move it below the if statements.

for username in $list
do
   #echo $username
   sleep $sleep
   VAL=`curl -s "$host$username" | jq -r ".id" | grep null`
   #echo $VAL
   if [[ $VAL == null ]]
   then
     echo -e "$username is available"
     echo "$username" >> username.free
   else
     echo -e "$username is taken"
   fi
done

Here is the code reworked to reduce the duplication:

#!/bin/bash

# variables
host='https://api.example.com/api/users/'
sleep=1

# check if jq install
if ! jq_loc="$(type -p "jq")" || [ -z "$jq_loc" ]; then
  echo "no jq installed."
  sleep 1
  echo "we're going to install it now."
  sleep 2
  sudo apt-get install jq
fi

if [ -n "$1" ] ; then
  # specified list
  list=`cat $1`
else
  # no list specified
  list=`echo {a..z}{a..z}{a..z}`
fi

for username in $list
do
   #echo $username
   sleep $sleep
   VAL=`curl -s "$host$username" | jq -r ".id" | grep null`
   #echo $VAL
   if [[ $VAL == null ]]
   then
     echo -e "$username is available"
     echo "$username" >> username.free
   else
     echo -e "$username is taken"
   fi
done

Rather than reading data into a variable and then working on that variable, a common technique is to just work on the data as it is read. To that end, I would offer the following edit of Micah's script:

#!/bin/bash

# variables
host='https://api.example.com/api/users/'
sleep=1

# check if jq install
type jq > /dev/null || sudo apt-get install jq

# Here is a bit of "magic".  We create a process to generate the data
# that we want to use as input and redirect its output to be the input
# of the script so that the subsequent read handles it. (Note that it
# is totally unnecessary to do this, and we could just as easily pipe
# this data directly to the while/read loop, but for some reason I 
# thought it would be instructive to see this technique.) 
exec < <(
if [ -n "$1" ] ; then
  cat $1
else
  echo {a..z}{a..z}{a..z} | tr ' ' \\n
fi
)

while read username 
do
   sleep $sleep
   if curl -s "$host$username" | jq -r ".id" | grep -q null
   then
     echo "$username is available"
     echo "$username" >> username.free
   else
     echo "$username is taken"
   fi
done

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM