I have shell script with 2 functions like below:
lines(){
while IFS="" read -l
do
line=$(wc -l < "something.txt")
if [ "$line" = "$1" ] ; then
do something...
echo "lines are: "$l""
else
#calling files function here
files
do something...
fi
done<something.txt
}
files(){
do something....
echo "something...\n""$(lines "$1")"
}
####Main
case "$1" in
lines)
shift
lines "$1"
;;
*)
esac
I am trying to run the script like this on an ubuntu machine:
sh files.sh line 3
I have some if operations where
In files I am trying to call lines function. When it's called and goes back to perform the actions in lines(), the argument I am trying to pass from the command line 3 i.e., "$1" is being passed as null (empty)
Can someone help me how I can have lines function read the parameter I am passing from the command line
Thanks
The easy thing to do is to just create a global array variable that preserves your original command-line arguments:
#!/usr/bin/env bash
[ "$BASH_VERSION" ] || { echo "ERROR: This script requires bash" >&2; exit 1; }
args=( "$0" "$#" )
func1() { func2 "local-arg1" "local-arg2"; }
func2() { echo "Function argument 1 is $1; original argument 2 is ${args[2]}"; }
func1
...will, if called as ./scriptname global-arg1 global-arg2, emit as output:
Function argument 1 is local-arg1; original argument 2 is global-arg2
Positional parameters are local to each function. So files can't access the $1 variable of lines by itself, you need to pass it explicitly:
files "$1"
I have the following code, that I want to be inside an function getsum(). I tried with the following code working without the function. When I run ./sum 5 6 I get 11.
#!/bin/bash
sum=0
for i in $#; do sum=$((sum+i)); done
echo $sum
exit 0
But how can I put it in a function doing the same job?
I tried the following code but it doesn't work.
#!/bin/bash
sums() {
sum=0
for i in $#; do sum=$((sum+i)); done
echo $sum
exit 0
}
sums
You just need to pass the arguments ($#) to the function sum() that you pass to your script:
#!/bin/bash
sums() {
sum=0
for i in $#; do sum=$((sum+i)); done
echo $sum
exit 0
}
sums "$#" # Note this line
I am trying to create a shell script using another script.
Following is the code.
#!/bin/bash
count=$#
cat << EOF > /tmp/kill_loop.sh
#!/bin/bash
while true;
do
for i in "$#"
do
echo $i
done
done
EOF
When I see kill_loop.sh , "$i" is empty.
#!/bin/bash
while true;
do
for i in "one two three"
do
echo
done
done
I want "$i" to be printed as such in kill_loop.sh file so that if i execute kill_loop.sh, it echoes the value 'one','two' and 'three'
Your "outer" shell script is interpreting $i as if it were one of its own variables, which isn't set, thus it evaluates to nothing. Try escaping the $ so the outer shell doesn't expand it:
echo \$i
here is the "foreach" function:
function foreach
{
typeset cmd=$1;
shift;
for arg in "$#";
do
$cmd $arg;
done
}
I have a function which takes another function as an argument and perform some operation.
e.g.
processFunc()
{
Func=$1
...
}
Now the problem is when i am passing a function which also accept multi line variable as argument.
e.g.
VAL="1\n2\n3\n4"
Func1()
{
VAL=$1
...
}
Now, there is no problem when I call direct function Func1()
e.g.
VAL2=`Func1 "$VAL"`
But an issue arises when I try to call proccessFunc()
e.g.
VAL3=`processFunc 'Func1 "$VAL"'` #Here is the problem...
Need help how to resolve the above problem.
Test code
#! /bin/bash
#set -x
func1()
{
VAL1="$1"
echo "$VAL1" ok
for i in $VAL1
do
echo $i
sleep 1
done
}
func2()
{
VALFUN="$1"
TIME=$2
COUNTER=1
while [ $COUNTER -le $TIME ]
do
# clear
$VALFUN
sleep 2
COUNTER=`expr $COUNTER + 1`
done
}
func3()
{
echo a
echo b
echo c
}
#### Main #####
LOCALVAL="`echo -e "123\nabc\nxyz"`"
#echo "$LOCALVAL"
echo "func1"
func1 "$LOCALVAL"
echo "func2 with func3"
func2 "func3" 3
echo "func2 wth func1"
func2 "func1 "$LOCALVAL"" 3
Error I am getting is:
./test.sh: line 18: [: abc: integer expression expected
Wouldn't that be great if you use the output from the Func1 and use it for the processFunc
So your code would be :
VAL="1\n2\n3\n4"
VAL2=Func1 "$VAL"
Where Func1 would be :
Func1()
{
VAL=$1
...
}
And then calling the processFunc as
VAL3=processFunc "$VAL"
Hope this helps.
Or Else what I suppose is that you are passing a string value where your shell is expecting a string.
And I believe the code should be :
a=123\nabc\nxyz
LOCALVAL = echo $a
You can do like this
VAL3="processFunc Func1 $VAL"
$VAL3
I'm attempting to write a function in bash that will access the scripts command line arguments, but they are replaced with the positional arguments to the function. Is there any way for the function to access the command line arguments if they aren't passed in explicitly?
# Demo function
function stuff {
echo $0 $*
}
# Echo's the name of the script, but no command line arguments
stuff
# Echo's everything I want, but trying to avoid
stuff $*
If you want to have your arguments C style (array of arguments + number of arguments) you can use $# and $#.
$# gives you the number of arguments.
$# gives you all arguments. You can turn this into an array by args=("$#").
So for example:
args=("$#")
echo $# arguments passed
echo ${args[0]} ${args[1]} ${args[2]}
Note that here ${args[0]} actually is the 1st argument and not the name of your script.
My reading of the Bash Reference Manual says this stuff is captured in BASH_ARGV,
although it talks about "the stack" a lot.
#!/bin/bash
shopt -s extdebug
function argv {
for a in ${BASH_ARGV[*]} ; do
echo -n "$a "
done
echo
}
function f {
echo f $1 $2 $3
echo -n f ; argv
}
function g {
echo g $1 $2 $3
echo -n g; argv
f
}
f boo bar baz
g goo gar gaz
Save in f.sh
$ ./f.sh arg0 arg1 arg2
f boo bar baz
fbaz bar boo arg2 arg1 arg0
g goo gar gaz
ggaz gar goo arg2 arg1 arg0
f
fgaz gar goo arg2 arg1 arg0
#!/usr/bin/env bash
echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#
Edit: please see my comment on question
Ravi's comment is essentially the answer. Functions take their own arguments. If you want them to be the same as the command-line arguments, you must pass them in. Otherwise, you're clearly calling a function without arguments.
That said, you could if you like store the command-line arguments in a global array to use within other functions:
my_function() {
echo "stored arguments:"
for arg in "${commandline_args[#]}"; do
echo " $arg"
done
}
commandline_args=("$#")
my_function
You have to access the command-line arguments through the commandline_args variable, not $#, $1, $2, etc., but they're available. I'm unaware of any way to assign directly to the argument array, but if someone knows one, please enlighten me!
Also, note the way I've used and quoted $# - this is how you ensure special characters (whitespace) don't get mucked up.
# Save the script arguments
SCRIPT_NAME=$0
ARG_1=$1
ARGS_ALL=$*
function stuff {
# use script args via the variables you saved
# or the function args via $
echo $0 $*
}
# Call the function with arguments
stuff 1 2 3 4
One can do it like this as well
#!/bin/bash
# script_name function_test.sh
function argument(){
for i in $#;do
echo $i
done;
}
argument $#
Now call your script like
./function_test.sh argument1 argument2
This is #mcarifio response with several comments incorporated:
#!/bin/bash
shopt -s extdebug
function stuff() {
local argIndex="${#BASH_ARGV[#]}"
while [[ argIndex -gt 0 ]] ; do
argIndex=$((argIndex - 1))
echo -n "${BASH_ARGV[$argIndex]} "
done
echo
}
stuff
I want to highlight:
The shopt -s extdebug is important. Without this the BASH_ARGV array will be empty unless you use it in top level part of the script (it means outside of the stuff function). Details here: Why does the variable BASH_ARGV have a different value in a function, depending on whether it is used before calling the function
BASH_ARGV is a stack so arguments are stored there in backward order. That's the reason why I decrement the index inside loop so we get arguments in the right order.
Double quotes around the ${BASH_ARGV[#]} and the # as an index instead of * are needed so arguments with spaces are handled properly. Details here: bash arrays - what is difference between ${#array_name[*]} and ${#array_name[#]}
You can use the shift keyword (operator?) to iterate through them.
Example:
#!/bin/bash
function print()
{
while [ $# -gt 0 ]
do
echo "$1"
shift 1
done
}
print "$#"
I do it like this:
#! /bin/bash
ORIGARGS="$#"
function init(){
ORIGOPT= "- $ORIGARGS -" # tacs are for sed -E
echo "$ORIGOPT"
}
The simplest and likely the best way to get arguments passed from the command line to a particular function is to include the arguments directly in the function call.
# first you define your function
function func_ImportantPrints() {
printf '%s\n' "$1"
printf '%s\n' "$2"
printf '%s\n' "$3"
}
# then when you make your function call you do this:
func_ImportantPrints "$#"
This is useful no matter if you are sending the arguments to main or some function like func_parseArguments (a function containing a case statement as seen in previous examples) or any function in the script.