I'm looking to provide a case statement based on whether a substring is within a filename.
Example Input
mysql_dumps/tpmysqldump-tps_dev_russell_development-information_schema-2014-03-26.sql
Code
case $DUMPFILE in
*"tpdata"*)
database="tpdata";;
*"tpmrbs"*)
database="tpmrbs";;
*"information_schema"*)
database="information_schema";;
*"performance_schema"*)
database="performance_schema";;
*)
echo "INVALID FILE";;
esac
How do you initialize $DUMPFILE? If I run the following, the output is information_schema, which is what I expected...
#!/bin/bash
DUMPFILE=mysql_dumps/tpmysqldump-tps_dev_russell_development-information_schema-2014-03-26.sql
case $DUMPFILE in
*"tpdata"*)
database="tpdata";;
*"tpmrbs"*)
database="tpmrbs";;
*"information_schema"*)
database="information_schema";;
*"performance_schema"*)
database="performance_schema";;
*)
echo "INVALID FILE";;
esac
echo $database
Related
New in Linux bash script.
Here I tried to create some files with getopts. For example I'd like to create 3 files called xyzfile, in command line ./createfiles -n xyzfile 3should be given (2 arguments after the option -n). The result should be 3 files with the names xyzfile_1, xyzfile_2 and xyzfile_3.
I tried to put my createfile() function outside the while-loop and as well as inside the while-loop. But the option -n doesn't work.
I also tried to create another function called foo() with included the function createfile(), but still something wrong there.
I have no idea anymore what I can do. Hope I can get some advices from you guys. Thank you very much!
#!/bin/bash
while getopts :n:bc opt; do
case $opt in
n) echo test 3333333
createfile() {
echo "$OPTARG"
sum=$2
for((i=1;i<=sum;i++))
do
touch "$OPTARG_${i}"
done
}
createfile $OPTARG ${2};;
b) echo "test 1111111";;
c) echo "test 2222222";;
*) echo error!;;
esac
done
Use a separate option for the count, and create your files after the option processing.
Something like:
while getopts "n:c:" opt; do
case $opt in
n) name="$OPTARG";;
c) count=$OPTARG;;
# other options...
esac
done
shift $((OPTIND -1))
while (( count > 0 )); do
touch "${name}_$count"
(( count-- ))
# ...
done
getopts supports only options without, or with one argument. So you'll have to decide on which way you want your script to work. You have multiple options:
add a new option -m or similar to pass the maximum number of files you want to create: createfile -n xyzfile -m 3
you can also use the arguments that are not passed as an option, if you do your parsing well then createfile 3 -n xyzfile or createfile -n xyzfile 3 would mean the same. In my scripts I often use such positional argument if there is one option that the user always needs to pass.
You might even consider changing your way of calling the script to createfile xyzfile -n 3 or even createfile xyzfile where the name is a positional argument and the number of files optional (choose a logical default value, probably 1)...
Parse the options first, then use the values you discover. An option can take only a single argument, so -n only gets the first one (I'll keep that as the file-name stem here). The count will be an ordinary positional argument found after parsing the options.
while getopts :n:bc opt; do
case $opt in
n) stem=$OPTARG; shift 2;;
b) shift 1;;
c) shift 1;;
*) shift 1; echo error ;;
esac
done
count=${1?No count given}
createfile () {
for ((i=$1; i<=$2; i++)); do
touch "${1}_${i}"
done
}
createfile "$stem" "$count"
I am trying to parse arguments in ksh. Can't do getopt for the same as in short options I have two/three characters. Currently I am using for loop. Its stupid but am unable to find something better.
Question: How do I set option+value as one unit in order to parse?
Also if eval set -- $option will help me then how do I use it? echo on option does not show the expected "--" at the end. Am I assuming something wrong?
I am thinking of using a variable to keep track of when an option is found but this method seems too confusing and unnecessary.
Thanks for your time and help.
Update 1:
Adding code as pointed out. Thanks to markp, Andre Gelinas and random down-voter in making this question better. Trying to execute the script as given in line 2 and 3 of code - or any other combination of short and long options passed together.
#!/bin/ksh
# bash script1.sh --one 123 --two 234 --three "some string"
# bash script1.sh -o 123 -t 234 -th "some string"
# the following creates problems for short options.
#options=$(getopt -o o:t:th: -l one:two:three: "--" "$#")
#Since the below `eval set -- "$options"` did not append "--" at the end
#eval set -- "$options"
for i in $#; do
options="$options $i"
done
options="$options --"
# TODO capture args into variables
Attempted code below TODO until now:
for i in $options; do
echo $i
done
Will be capturing the args using:
while true; do
case $1 in
--one|-o) shift; ONE=$1
;;
--two|-t) shift; TWO=$1
;;
--three|-th) shift; THREE=$1
;;
--) shift; break
;;
esac
done
Try something like this :
#!/bin/ksh
#Default value
ONE=123
TWO=456
# getopts configuration
USAGE="[-author?Andre Gelinas <andre.gelinas#foo.bar>]"
USAGE+="[-copyright?2018]"
USAGE+="[+NAME?TestGetOpts.sh]"
USAGE+="[+DESCRIPTION?Try out for GetOps]"
USAGE+="[o:one]#[one:=$ONE?First.]"
USAGE+="[s:second]#[second:=$TWO?Second.]"
USAGE+="[t:three]:[three?Third.]"
USAGE+=$'[+SEE ALSO?\aman\a(1), \aGetOpts\a(1)]'
while getopts "$USAGE" optchar ; do
case $optchar in
o) ONE=$OPTARG ;;
s) TWO=$OPTARG ;;
t) THREE=$OPTARG ;;
esac
done
print "ONE = "$ONE
print "TWO = "$TWO
print "THREE = "$THREE
You can use either --one or -o. Using --man or --help are also working. Also -o and -s are numeric only, but -t will take anything. Hope this help.
I'm trying to trim only the left half of a string that is given to ltrim() as an argument. This is my current code.
ltrim()
{
string=${1}
divider=$((${#string} / 2))
trimrule=${2}
string_left=${string:0:$divider}
string_right=${string:$divider}
echo ${string:$divider} ## My own quick debug lines
echo ${string:0:$divider} ## My own quick debug lines
if [ $# -ne 2 ]
then
printf "%d argument(s) entered. 2 required.\n" "$#"
else
while :
do
case $string_left in
${2}*) string_left=${string_left#?} ;;
*${2}) string_left=${string_left%?} ;;
*) break ;;
esac
done
printf "Left side string is %s\n" "${string_left}"
fi
}
However, when I enter ltrim abcdefghijklmnopq abc the shell returns the following:
ijklmnopq
abcdefgh
Left side string is bcdefgh
So I only lost 'a' out of the word while I'm looking to get 'defgh' as a result. What am I doing wrong?
function substr_remove() {
echo "${1//$2/}"
}
substr_remove carfoobar123foo456 foo
Output:
carbar123456
Are you searching for something like this?
function ltrim() {
echo ${1##$2}
}
ltrim abcdefghijklmnopq abc # Prints: defghijklmnopq
I am trying to see if a string is part of another string in shell script (#!bin/sh).
The code i have now is:
#!/bin/sh
#Test scriptje to test string comparison!
testFoo () {
t1=$1
t2=$2
echo "t1: $t1 t2: $t2"
if [ $t1 == "*$t2*" ]; then
echo "$t1 and $t2 are equal"
fi
}
testFoo "bla1" "bla"
The result I'm looking for, is that I want to know when "bla" exists in "bla1".
Thanks and kind regards,
UPDATE:
I've tried both the "contains" function as described here: How do you tell if a string contains another string in Unix shell scripting?
As well as the syntax in String contains in bash
However, they seem to be non compatible with normal shell script (bin/sh)...
Help?
When using == or != in bash you can write:
if [[ $t1 == *"$t2"* ]]; then
echo "$t1 and $t2 are equal"
fi
Note that the asterisks go on the outside of the quotes and that the wildcard pattern must be on the right.
For /bin/sh, the = operator is for equality only, not pattern matching. You can use case for pattern matching though:
case "$t1" in
*"$t2"*) echo t1 contains t2 ;;
*) echo t1 does not contain t2 ;;
esac
If you're specifically targeting Linux, I would assume the presence of /bin/bash.
I am trying to merge two very different scripts together for consolidation and ease of use purposes. I have an idea of how I want these scripts to look and operate, but I could use some help getting started. Here is the flow and look of the script:
The input file would be a standard text file with this syntax:
#Vegetables
Broccoli|Green|14
Carrot|Orange|9
Tomato|Red|7
#Fruits
Apple|Red|15
Banana|Yellow|5
Grape|Purple|10
The script would take the input of this file. It would ignore the commented portions, but use them to dictate the output. So based on the fact that it is a Vegetable, it would perform a specific function with the values listed between the delimiter (|). Then it would go to the Fruits and do something different with the values, based on that delimiter. Perhaps, I would add Vegetable/Fruit to one of the values and dependent on that value it would perform the function while in this loop to read the file. Thank you for your help in getting this started.
UPDATE:
So I am trying to implement the IFS setup and thought of a more logical arrangement. The input file will have the "categories" displayed within the parameters. So the setup will be like this:
Vegetable|Carrot|Yellow
Fruit|Apple|Red
Vegetable|Tomato|Red
From there, the script will read in the lines and perform the function. So basically this type of setup in shell:
while read -r category item color
do
if [[ $category == "Vegetable" ]] ; then
echo "The $item is $color"
elif [[ $category == "Fruit" ]] ; then
echo "The $item is $color"
else
echo "Bad input"
done < "$input_file"
Something along those lines...I am just having trouble putting it all together.
Use read to input the lines. Do a case statement on their prefix:
{
while read DATA; do
case "$DATA" in
\#*) ... switch function ...;;
*) eval "$FUNCTION";;
esac
done
} <inputfile
Dependent on your problem you might want to experiment with setting $IFS before reading and read multiple variables in 1 go.
You can redefine the processing function each time you meet a # directive:
#! /bin/bash
while read line ; do
if [[ $line == '#Vegetables' ]] ; then
process () {
echo Vegetables: "$#"
}
elif [[ $line == '#Fruits' ]] ; then
process () {
echo Fruits: "$#"
}
else
process $line
fi
done < "$1"
Note that the script does not skip empty lines.