Syntax Error at Line * ) `in Ksh? - shell

Im trying to execute the following code in Unix and getting the Above Error ,
Please Hep me to correct the code
SERVER_NM=`uname -n`
case $SERVER_NM in
infad1) export ETL_SYS=TST
;;
infasa1) export ETL_SYS=TST
;;
infasb1) export ETL_SYS=TST
;;
infap1) export ETL_SYS=PRD
;;
infap2) export ETL_SYS=PRD
;;
infap3) export ETL_SYS=PRD
;;
infap4) export ETL_SYS=PRD
;;
*) echo "No Dir";;
esac
when i execute this im getting
unexpected4]: syntax error at line 5 : `in and im using !/usr/bin/ksh

Is there a chance you have funny characters like carriage returns (\r) in your script?
Please run od -c yourscript to find out and if so, use a better editor that can display funny characters (vim) or dos2unix yourscript.

export SERVER_NM=`uname -n`
case $SERVER_NM in
infad1|infasa1|infasb1) export ETL_SYS=TST ;;
infap1|infap2|infap3|infap4) export ETL_SYS=PRD ;;
*) echo "No Dir" ;;
esac
echo $ETL_SYS

SERVER_NM="`uname -n`"
echo "${SERVER_NM}" | sed 's/infad1.*/PRD/;t;s/infasa1.*/PRD/;t;s/infasb1/TST/;t;s/infap[1-4].*/PRD/;t;s/.*/No Dir/' | read Tempo
export ETL_SYS="${Tempo}"
quicker maybe (depending of use of SERVER_NM)
export ETL_SYS="`uname -n | sed 's/infad1.*/PRD/;t;s/infasa1.*/PRD/;t;s/infasb1/TST/;t;s/infap[1-4].*/PRD/;t;s/.*/No Dir/'`"

Related

How to handle errors in getopt

Based on tutorials I found here and here getopt should provide me with information about errors using some combination of characters :?*.
But when I used this code:
#!/bin/bash
eval set -- "$(getopt -o hspna: --long help,server,project,name-prefix,action: -- "$#")"
while [ : ]; do
case "$1" in
-s | --server)
echo "Setting server"
shift
;;
-p | --project)
echo "Setting project"
shift
;;
-n | --name-prefix)
echo "Setting name prefix"
shift
;;
-a | --action)
echo "Setting action"
shift
;;
--)
shift
break
;;
-h | --help)
echo "Providing help 1"
exit
;;
:)
echo "Providing help 2"
exit
;;
?)
echo "Providing help 3"
exit
;;
*)
echo "Providing help 4"
exit
;;
esac
done
echo $#
echo "Configured"
exit
Then following command that was supposed to show an error gave me the following output:
$ ./debug.sh -a -s -b -- foo bar baz
getopt: invalid option -- 'b'
Setting action
Setting server
foo bar baz
Configured
I was expecting that:
Providing help 2 will appear due to -a missing a value
Providing help 3 will appear due to -b not being a valid parameter
Providing help 4 will appear due to overall errors
Configured should never appear since the previous 3 points have an exit
But none of the above was true.
Also when testing further even more things did not work as expected.
# Expecting error due to missing value for `-a` but instead everything worked fine
$ ./debug.sh -a -s
Setting action
Setting server
Configured
# This time I expected everything to work fine, since I provided `X` as value of `-a`, but error was shown.
$ ./debug.sh -aX
Setting action
Providing help 3
What am I doing wrong?
What am I doing wrong?
Util-linux getopt prints and handles errors.
if ! args="$(getopt \
-n your_command \
-o hspna: \
--long help,server,project,name-prefix,action: \
-- "$#"\
)"; then
exit 1
fi
eval "set -- $args"
...
$ ./util -a
your_command: option requires an argument -- 'a'
I was expecting that:
I do not understand why. There is no such documentation in getopt. No, getopt will not output ? nor :. You can handle your (as the author of the program) errors, like you forgot to handle the option in case that you have given to getopt - you handle that with *).
The ? is a glob that matches any character. Because you forgot a shift after esac before done, X remains in $1, which is one character and is matched by ?). You meant '?'). This should go into *) case, and you should print yourself an error message.
Example, subjective in my style that I use (many people do not like set -eu):
set -euo pipefail
args=$(getopt -o ab -- "$#")
eval "set -- $args"
aflag=0
while (($#)); do
case "$1" in
-a) afloag=1; ;;
--) shift; break;
*) echo "Och no, I forgot about -b, or some other error!" >&2; exit 1; ;;
easc
shift
done

Why do shortened versions of long options work with getopt?

In the following script:
#!/usr/bin/env bash
func_usage ()
{
cat <<EOF \
USAGE: ${0} \
EOF
}
## Defining_Version
version=1.0
## Defining_Input
options=$(getopt -o "t:" -l "h,help,v,version,taxonomy:" -a -- "$#")
eval set -- "$options"
while true;do
case $1 in
-h|--h|-help|--help)
func_usage
exit 0
;;
-v|--v|-version|--version)
echo $version
;;
-t|--t|-taxonomy|--taxonomy)
echo "Option t = $2 ";
Taxonomy_ID=$2
echo $Taxonomy_ID
shift
;;
--)
shift
break;;
esac
shift
done
## Defining Taxonomy Default Value (in case is not provided)
TaxonomyID=${Taxonomy_ID:=9606};
echo $TaxonomyID
exit 0
The commands:
./script.sh -v
./script.sh --v
./script.sh -version
./script.sh --version
Work as expected. But what I do not understand is why the commands:
./script.sh -ver
./script.sh --ver
work at all. An equivalent unexpected behavior is also observed for the commands:
./script.sh -tax 22
./script.sh --tax 22
I would be grateful to get an explanation and/or a way to correct this unexpected behavior.
Note that getopt is an external utility unrelated to Bash.
what I do not understand is why the commands: .. work at all.
Because getopt was designed to support it, there is no other explanation. From man getopt:
[...] Long options may be abbreviated, as long as the abbreviation is not ambiguous.
Unambiguous abbreviations of long options are converted to long options.
Based on the comments I have received, specially from #CharlesDuffy, I have modified my code to what I believe is a more robust and compatible version. Importantly, the code below addresses the pitfalls of the original code
#!/usr/bin/env bash
func_usage ()
{
cat <<EOF
USAGE: ${0}
EOF
## Defining_Version
version=1.0
## Defining_Input
while true;do
case $1 in
-h|--h|-help|--help|-\?|--\?)
func_usage
exit 0
;;
-v|--v|-version|--version)
echo $version
;;
-t|--t|-taxonomy|--taxonomy)
echo "Option t = $2 ";
Taxonomy_ID=$2
echo $Taxonomy_ID
shift
;;
--)
shift
break;;
-?*)
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
;;
*)
break
esac
shift
done
TaxonomyID=${Taxonomy_ID:=9606};
echo $TaxonomyID
exit 0
The code above behaves as expected in that the commands:
./script -tax 22
Gives the warning:
WARN: Unknown option (ignored): -tax
9606
As expected

Bash script has unexpected token `;;'

I have a Bash command that is generated by a buck Python script:
platform=$(case $(uname) in
"Linux") echo "linux-x86_64" ;;
"Darwin") echo "darwin64-x86_64-cc" ;;
*) echo "Unknown" esac);
cp -r $SRCDIR $OUT && cd $OUT && ./Configure shared $platform --prefix=$OUT/build --openssldir=$OUT/build/openssl && make && make install
When I try to execute it, I get the following error:
unexpected token `;;'
What have I done wrong here?
I am on the latest macOS.
A much clearer and more efficient way to write the code would be:
case $(uname) in
"Linux") platform="linux-x86_64" ;;
"Darwin") platform="darwin64-x86_64-cc" ;;
*) platform="Unknown" ;;
esac
Having the result of echo captured by $() is something of a shell anti-pattern. Why write to stdout and read from stdin when you can simply use the text directly?
The closing ) on the "Linux" case is terminating the process substitution. Since it's bash, just use matching parens in the case:
platform=$(case $(uname) in
("Linux") echo "linux-x86_64" ;;
("Darwin") echo "darwin64-x86_64-cc" ;;
(*) echo "Unknown";;
esac
)
(Also, note that I had to add ;; after the default case.)
I would use something like:
get_platform() {
case "${1,,}" in
darwin*) echo darwin64... ;;
freebsd*) echo freebsd... ;;
linux*) echo linux-x86_64.. ;;
cygwin*) echo cyg... ;;
*) return 1;;
esac
return 0
}
platform=$(get_platform "$OSTYPE" || get_platform $(uname))
echo "${platform:-Unknown}"
Double check - bash stores the operating system in the $OSTYPE variable. In case of fail (other shells), it still trying to use the uname.
In the case of undetected OS, the final decision, is populated to the main script (return 1) so you can check and adjust it as you want, like echo "${platform:-Unknown}".

Eval invoked by a bash script file

Hi I'm creating a bash script to improve my job. If I have some files in a directory such as
file1.dat
file2.dat
file3.dat
file1.inp
file2.inp
file3.fal
I must digit in a shell the following command
PBS_nastran ver=20101 mem=48Gb mod=i8 i=file1.dat
PBS_nastran ver=20101 mem=48Gb mod=i8 i=file2.dat
PBS_nastran ver=20101 mem=48Gb mod=i8 i=file3.dat
PBS_abaqus ver=6133 ncpu=16 j=file1.inp
PBS_abaqus ver=6133 ncpu=16 j=file2.inp
PBS_falancs j=file1.fal
I've created a symple script
code='nastran'
case $code in
abaqus) command="PBS_abaqus ver=6133 ncpu=16 j="
ext=".inp";;
nastran) command="PBS_nastran ver=20101 mem=48Gb mod=i8 i="
ext=".dat";;
falancs) command="PBS_falancs j="
ext=".fal";;
esac
file_list=$(ls * | grep "$ext$")
file_list=${file_list//"./"/}
file_list=$(echo $file_list | tr " " "\n")
for file in $file_list
do
command=$command$file
eval $command
done
this it's ok and work correctly. The next step in a optimization process it's to put the code in a *.sh file and I create this
#!/bin/bash
case $1 in
abaqus) command='PBS_abaqus ver=6133 ncpu=$3 j='
ext='.inp';;
nastran) command='PBS_nastran ver=20101 mem=48Gb mod=i8 i='
ext='.dat';;
falancs) command='PBS_falancs j='
ext='.fal';;
esac
if [ -z $2 ]
then
file_list=$(ls | grep -E "[0-9]{8}_[[:alnum:]].*_RUN_[[:alnum:]].*${ext}$")
file_list=${file_list//"./"/}
file_list=$(echo $file_list | tr " " "\n")
else
file_list=$2
fi
for file in $file_list
do
command=$command$file
eval "$command"
done
but if I lunch script "./script.sh nastran" there is an error:
./lancia.sh: line26: PBS_nastran: command not found
I think that the problem is in the interpretation of blank space but I don't understand the way to fix it.
Thank for your help
You should rarely need to use eval, and this is no exception. You can store a command name in a variable, but you should not store an entire command line. Put the arguments in an array to ensure they remain properly quoted.
Also, do not try to parse the output of ls; use patterns to match the files you want. (It is unfortunate, though, that you can't use bracket expressions like {8} with patterns.)
#!/bin/bash
num_cpus=${3:-1}
case $1 in
abaqus)
cmd_name=PBS_abaqus
cmd_options=( ver=6133 "ncpu=$num_cpus")
file_option="j"
ext='.inp'
;;
nastran)
cmd_name=PBS_nastran
cmd_options=( ver=20101 mem=48Gb mod=i8)
file_option="i"
ext='.dat'
;;
falancs)
cmd_name=PBS_falancs
cmd_options=()
file_option="j"
ext='.fal'
;;
*) echo "Unrecognized name '$1', aborting" >&2
exit 1
esac
if [ -z "$2" ]; then
file_list=( [[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]][[:digit:]]_[[:alnum:]]*_RUN_[[:alnum:]]*$ext )
else
file_list=( $2 ) # I'm assuming here $2 is intended to be a pattern
fi
for file in "${file_list[#]}"; do
do
"$cmd_name" "${cmd_options[#]}" "$file_option=$file"
done

Bash long options/flags - how to do it?

I am trying to change my working script with getopts to getopt ( long flags ).
Below i present my code which is working.
getopts 'm:' mode
modeValue=$OPTARG
getopts 'p:' parameter
parameterValue=$OPTARG
getopts 'u:' parameter
parameterValue2=$OPTARG
getopts 'l:' parameter
parameterValue3=$OPTARG
getopts 'n:' parameter
parameterValue4=$OPTARG
getopts 'e:' parameter
parameterValue5=$OPTARG
getopts 'w:' parameter
parameterValue6=$OPTARG
getopts 'r:' parameter
parameterValue7=$OPTARG
case $modeValue in
addRepository)
doAddRepository "$parameterValue" "$parameterValue7"
exit $?
;;
addProject)
doAddProject "$parameterValue"
exit $?
;;
addUser)
doAddUser "$parameterValue2" "$parameterValue4" "$parameterValue5" "$parameterValue6"
exit $?
;;
assignProject)
doAssignProject "$parameterValue" "$parameterValue2" "$parameterValue3"
exit $?
;;
*)
#echo "$doShowUsage"
exit 1
;;
esac
Now my script is working like example below:
For add repository: ./script.sh -m addRepository -p NameOfTheProject -r NameOfTheRepository
I want to edit this for something like this:
./script.sh --mode addRepository --project NameOfTheProject --repo NameOfTheRepository
I started to modify code and added something what i present below:
TEMP=`getopt -o m:p:u:l:n:e:c:r: --long mode:,project:,username:,level:,name:,email:,pass:,repo: -n 'test.sh'
-- "$#"` eval set -- "$TEMP"
while true ; do
case "$1" in
-m|--mode)
case "$2" in
addRepository)
doAddRepository=$2 ; shift 2 ;;
addProject)
doAddProject=$2 ; shift 2 ;;
addUser)
doAddUser=$2 ; shift 2 ;;
assignProject)
doAssignProject=$2 ; shift 2 ;;
esac ;;
-h|--help)
case "$2" in
*) echo "$doShowUsage"
exit 1
esac ;;
esac done
My question is : Am I doing it in the right way ? How can I add parameters to the functions "doAddProject/Repository/User...?" Can someone give me some advices? Above functions got different amount of parameters so take a look at it.
Thank you!
Stephane Chazelas wrote a very fine getops-long shell script that I use in my bash debugger. You can copy that script and use it.
If you run that program setting variable test_getopts_long, e.g.
test_getopts_long=1 bash getopts_long.sh
you'll see extensive examples for how to use, and it tests itself.

Resources