1

i have bash script which do some function with website domains like following

#!/usr/bin/env bash
domain="$1";
function A(){
ping $domain -c 4
}

function B(){
host $domain
}

A;
B;

and when i run this script by doing ./script.sh whateverdomain.com it works well. BUT i heard that with array i can run the script against some of domains seperated by comma for example. like ./script.sh domain1.com,domain2.com and it will excute the whole script function against the first one then the second one and i tried the following code.

my_arr=($(echo $DOMAIN | tr "," "\n"))
d=$(for domain in "${my_arr[@]}" ; 
do echo $domain
done)

pingme(){
ping -c 4 $d
}

but it hanging and not passing each domain to variable $d so i need to define array as function and when i run the script it pass domain and execute the script functions then repeat the whole script against the second domain and so on like.

#!/usr/bin/env bash
domain="$1";

function myarray(){
# the array function which will pass the domains one by one
}

function A(){
ping $domain -c 4
}

function B(){
host $domain
}

myarray;
A;
B;
5
  • 2
    Pass the arguments separately: ./script.sh domain1.com domain2.com and iterate over the elements of "$@" in the script: for domain in "$@"; do …; done. That is the natural way to write shell scripts. Also pass the domain explicitly to the function — global variables are problematic. If you must use the comma-separated argument, then use: for domain in "${my_arr[@]}"; do pingme $domain; done — and the functions should process $1, not a global variable. Inside a function, $1 is the argument passed to the function, not to the script as a whole. Commented Aug 11, 2020 at 12:43
  • 1
    In addition to everything said above, see BashPitfalls #50 (about that particular mechanism for splitting a string into an array) and wiki.bash-hackers.org/scripting/obsolete (about the function keyword). Commented Aug 11, 2020 at 12:49
  • @JonathanLeffler if i don`t use global variable how would i define the variable in each function without running the for loop in each function ! Commented Aug 11, 2020 at 13:12
  • In the text you posted, my_arr=($(echo $DOMAIN | tr "," "\n")) is the only place I see $DOMAIN capitalized. Commented Aug 11, 2020 at 13:20
  • could you be more clarify please about what you means ! Commented Aug 11, 2020 at 13:59

1 Answer 1

2

Converting comments into an answer.

The natural way to write shell scripts is to pass the arguments separately:

./script.sh domain1.com domain2.com

and iterate over the elements of "$@" in the script, passing the domain names explicitly to the function (as shown) — global variables are just as problematic in shell scripts as in other programming languages.

#!/usr/bin/env bash

A() { ping "$1" -c 4; }
B() { host "$1"; }

for domain in "$@"
do
    A $domain
    B $domain
done

If you must use the comma-separated argument, then use:

domains=($(echo "$1" | tr "," "\n"))

pingme() { ping "$1" -c 4; }

for domain in "${domains[@]}"
do
    pingme $domain
done

and (as before) the function should process $1, not a global variable.

Inside a function, $1 is the first argument passed to the function, not what's passed to the script as a whole.

Note that in the original code, none of the semicolons is needed. In the code I wrote, the semicolons before the close braces are needed because I lazily wrote the functions on a single line (because they are so simple — I would probably not use functions for such simple commands, especially as they're each only invoked once in the script). If they were spread over three or four lines, the semicolons would not be needed.

A()
{
    ping "$1" -c 4
}

Also, you don't need to use the keyword function — and it is generally regarded as a bad idea to do so. As Charles Duffy noted in a comment, the Bash Hackers wiki indicates you should not use function.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for clarification, it works when i get the whole thing together. one more thing , i use global variable as following domain="$1"; mkdir -p $(pwd)/$domain-$(date +"%H-%M-%S-%d-%m-%y"); WORKING_DIR="$(pwd)/$domain-$(date +"%H-%M-%S-%d-%m-%y")"; because my script contains more than one function so i need to pass variable $domain in each function which would be certain char because it is timed as u see but in general for loop worked as u described. Thanks Sir

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.