My code:
#!/bin/bash
for i in $#;
do echo $i;
done;
run script:
# ./script 1 2 3
1
2
3
So, I want to skip the first argument and get:
# ./script 1 2 3
2
3
Use the offset parameter expansion
#!/bin/bash
for i in "${#:2}"; do
echo $i
done
Example
$ func(){ for i in "${#:2}"; do echo "$i"; done;}; func one two three
two
three
Use shift command:
FIRST_ARG="$1"
shift
REST_ARGS="$#"
Look into Parameter Expansions in the bash manpage.
#/bin/bash
for i in "${#:2}"
do echo $i
done
You could just have a variable testing whether it's the first argument with something like this (untested):
#!/bin/bash
FIRST=1
for i in $#
do
if [ FIRST -eq 1 ]
then
FIRST=0
else
echo $i
fi
done
Related
My problem is pretty simple. I have :
a=$(echo "lol")
for i in {1..3};
do
echo $a && echo $i ;
done
I get :
lol
1
lol
2
lol
3
I would like to print only once the variable a at the beginning of the output , to get :
lol
1
2
3
Any idea?
You don't need a loop at all
a=$(echo "lol") # Not sure why poster wrote this rater than a=lol
printf %s\\n "$a" {1..3}
I suggest:
#!/bin/bash
a="lol"$'\n' # append newline
for i in {1..3}
do
echo -e "$a$i" # -e: enable interpretation of escape sequences
unset a
done
Or replace in your question
echo $a && echo $i ;
with
[[ "$i" == "1" ]] && echo "$a"
echo "$i"
See: help echo and help unset
Move the echo outside of the for loop
a=$(echo "lol")
echo $a
for i in {1..3}; do
echo $i;
done
or:
echo "lol"
for i in {1..3}; do
echo $i;
done
test run in shell
I would like to update a script that is currently like this:
$ example.sh a b
Here is the code within example.sh
for var in "$#"
do
$var
done
Where it takes in arguments and those arguments are looped over and executed (assuming those arguments exist).
I would like to update the script so that these flags are the scripts / functions and that everything after is applied as the argument to the function.
$ example.sh --a 1 2 3 --b 4 5 6
I would like to loop over all flags and run the equivalent of.
a 1 2 3
b 1 2 3
I have looked into getopts but I am not sure if it will allow me to execute and pass in the arguments the way I would like.
What I tried:
while getopts ":a:b:c:d:" opt; do
case "$opt" in
a) i=$OPTARG ;;
b) j=$OPTARG ;;
c) k=$OPTARG ;;
d) l=$OPTARG ;;
esac
done
echo $i
echo $j
for file in "$#"; do
echo $file
done
I found the following script which given example --a 1 2 3 --b 4 5 6 will only assign the first item using OPTARG and it doesn't work properly. I am unsure how to apply arguments to a function in this format.
I don't know of any automatic way to do what you want, but you can just loop through your arguments and construct your commands, like this:
#!/bin/bash
cmd=()
while [ $# -gt 0 ]; do # loop until no args left
if [[ $1 = --* ]]; then # arg starts with --
[[ ${#cmd[#]} -gt 0 ]] && "${cmd[#]}" # execute previous command
cmd=( "${1#--}" ) # start new array
else
cmd+=( "$1" ) # append to command
fi
shift # remove $1, $2 goes to $1, etc.
done
[[ ${#cmd[#]} -gt 0 ]] && "${cmd[#]}" # run last command
Perhaps this way.
cat example.sh
while read line;do
$line
done <<<$(echo $# | sed 's/--/\n/g')
and I try that
./example.sh '--echo 1 2 3 --dc -e 4sili5+p'
output
1 2 3
9
I have a small problem here.
I've written a script, which works fine. But there is a small problem.
The script takes 1 or 2 arguments. The 2nd arguments is a .txt file.
If you write something like my_script arg1 test.txt, the script will work. But when you write my_script arg1 < test.txt it doesn't.
Here is a demo of my code:
#!/bin/bash
if [[ $# = 0 || $# > 2 ]]
then
exit 1
elif [[ $# = 1 || $# = 2 ]]
then
#do stuff
if [ ! -z $2 ]
then
IN=$2
else
exit 3
fi
fi
cat $IN
How can I make it work with my_script arg1 < test.txt?
If you just want to change how my_script is called, then just let cat read from myscript's standard input by giving it no argument:
#!/bin/bash
if [[ $# != 0 ]]
then
exit 1
fi
cat
If you want your script to work with either myscript arg1 < test.txt or myscript arg1 test.txt, just check the number of arguments and act accordingly.
#!/bin/bash
case $# in
0) exit 1 ;;
1) cat ;;
2) cat $2 ;;
esac
If you look at how the guys at bashnative implemented their cat you should be able to use 'read' to get the piped content..
eg. do something like this:
while read line; do
echo -n "$line"
done <"${1}"
HTH,
bovako
I am trying to figure out a sane way to do a NOT clause in a case. The reason I am doing this is for
transcoding when a case is met, aka if I hit an avi, there's no reason to turn it into an avi again, I can
just move it out of the way (which is what the range at the base of my case should do). Anyway, I have some
proto code that I wrote out that kind of gives the gist of what I am trying to do.
#!/bin/bash
for i in $(seq 1 3); do
echo "trying: $i"
case $i in
! 1) echo "1" ;; # echo 1 if we aren't 1
! 2) echo "2" ;; # echo 2 if we aren't 2
! 3) echo "3" ;; # echo 3 if we aren't 3
[1-3]*) echo "! $i" ;; # echo 1-3 if we are 1-3
esac
echo -e "\n"
done
expected results would be something like this
2 3 ! 1
1 3 ! 2
1 2 ! 3
Help is appreciated, thanks.
This is contrary to the design of case, which executes only the first match. If you want to execute on multiple matches (and in your design, something which is 3 would want to execute on both 1 and 2), then case is the wrong construct. Use multiple if blocks.
[[ $i = 1 ]] || echo "1"
[[ $i = 2 ]] || echo "2"
[[ $i = 3 ]] || echo "3"
[[ $i = [1-3]* ]] && echo "! $i"
Because case only executes the first match, it only makes sense to have a single "did-not-match" handler; this is what the *) fallthrough is for.
You can do this with the extglob extension.
$ shopt -s extglob
$ case foo in !(bar)) echo hi;; esac
hi
$ case foo in !(foo)) echo hi;; esac
$
I currently encountered a tricky problem on which I couldn't find any solution yet.
I wrote a script like this:
#!/bin/sh
x=1
while [ "$x" -le $# ]; do
echo "$x"'. Argument is: ' "\$$x"
x="$(( $x + 1 ))"
done
I suggested that the shell would evaluate the expression "\$$x" after expanding the variables to get access to the argument on position x but the output is:
1. Argument is: $1
Please help. Thx in advance.
Here is the fix
$ cat a.sh
#!/bin/sh
x=1
while [ "$x" -le $# ]; do
echo "$x"'. Argument is: ' "${!x}" # If you need indirect expansion, use ${!var} is easier way.
x="$(( $x + 1 ))"
done
Test result
$ sh a.sh a b c
1. Argument is: a
2. Argument is: b
3. Argument is: c
This code should work:
#!/bin/sh
x=0
args=($#)
while [ "$x" -lt $# ]; do
echo "$x"'. Argument is: ' "${args[${x}]}"
x="$(( $x + 1 ))"
done