2 grep in if statement - bash

Anyone can tell me what will be the problem?i know that this is a half sec problem but pls help:) egrep "first" a.sh && egrep "second" a.sh works, a.sh contains first,second,third etc.. Thx!
if [[ egrep "first" a.sh && egrep "second" a.sh ]]; then
echo "success"
fi

Your problem is that you're using the [[ command. Use just the greps.
if egrep ... && egrep ... ; then

I think this may be what you are looking to do:
found_1=$(egrep "first" a.sh)
found_2=$(egrep "second" a.sh)
if [[ -n "$found_1" ]] && [[ -n "$found_2" ]]; then
echo "success"
fi

Related

getops still performs default actions when arguments are provided

I've recently started working with the getopts command in bash. I am confused as to why my script runs the dafult action "cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl" when arguments have been provided. I only want that to run if no arguments were passed to the shell script. I've used getopts:Std in perl where I was able to code somthing like:
unless ($opts{d}) {
do something...}
How would I code something like that in a shell script? Also, how would I code logic such as this:
if ($opts{c}) {
cat ~bin/Temp/mag.txt | ~bin/Scripts/report.pl -c
}
elsif ($opts{d} {
cat ~bin/Temp/mag.txt | ~bin/Scripts/report.pl -d
My code:
#!/bin/sh
while getopts cd name
do
case $name in
c)copt=1;;
d)dopt=1;;
*)echo "Invalid arg";;
esac
done
if [[ ! -z $copt ]] #Specifies what happens if the -c argument was provided
then
echo "CSV file created!"
cat "~/bin/Temp/log.txt" | ~/bin/Scripts/vpnreport/report.pl -c
fi
if [[ ! -z $dopt ]] #Specifies what happens if the -d argument was provided
then
echo "Debug report and files created"
cat ~bin/Temp/mag.txt | ~bin/Scripts/report.pl -d
fi
if [[ ! -z $name ]] #Specifies what happens if no argument was provided
then
echo "Running standard VPN report"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl
fi
shift $(($OPTIND -1))
My Output:
[~/bin/Scripts/report]$ sh getoptstest.sh
Running standard report
[~/bin/Scripts/report]$ sh getoptstest.sh -d
Debug report and files created
Running standard report
[~/bin/Scripts/report]$
The two getopts commands are vasty different from bash to perl and I just can't seem to get the hang of the bash varient even after reading several tutorials. Any help would be greatly appreciated!
On the final run of getopts, your variable (name) will be set to "?".
#!/bin/bash
while getopts abc foo; do :; done
echo "<$foo>"
Output of the above:
$ ./mytest.sh
<?>
$ ./mytest.sh -a
<?>
Insead, use elif, which is like Perl's elsif:
if [[ ! -z $copt ]]
then
# ...
elif [[ ! -z $dopt ]]
then
# ...
else
# ...
fi
Or test if [[ -z $copt && -z $dopt ]], or so forth. Other notes:
See the official if and case documentation in the Bash manual under "Conditional Constructs".
[[ ! -z $name ]] means the same as the more-direct [[ -n $name ]].
Use #!/bin/bash instead of #!/bin/sh, or switch off of [[ in favor of [. The double square bracket (and your use thereof) is specific to bash, and rarely works with sh.
I took Jeff's answer and rewrote my script so it works now:
#!/bin/bash
while getopts cd name
do
case $name in
c)carg=1;;
d)darg=1;;
*)echo "Invalid arg";;
esac
done
#Specifies what happens if the -c argument was provided:
if [[ ! -z $carg ]]
then
if [[ -z $darg ]]
then
echo "CSV created"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl -c
else
echo "Debug CSV created"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl -cd
fi
fi
#Specifies what happens if the -d argurment was provided:
if [[ ! -z $darg ]]
then
echo "Debug report created"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl -d
#Specifies what happens if no argument was provided:
else
echo "Standard report created"
cat ~bin/Temp/logs.txt | ~bin/Scripts/report.pl
fi
Thank you again for your assistance!

Search for exact string

I'm trying to search for exact string located in chars number 4-7.
When I run the cut command on terminal it works,
however in a script it fails as I believe the if statement provide me "0".
This is what I've done:
for NAME in `cat LISTS_NAME`; do
if [[ John == cut -c 4-7 "${NAME}" ]]; then
Do Something ...
fi
if [[ Dana == cut -c 4-7 "${NAME}" ]]; then
Do Something...
fi
Can you advise me how to run this using cut or any other reg-ex?
You aren't running the cut command there. You are comparing John and Dana to the literal string cut -c 4-7 <value-of-$NAME>.
You need to use:
if [[ John == $(cut -c 4-7 "${NAME}") ]]; then
etc.
That being said you should only do the cut call once and store that in a variable. And for exact matching you need to quote the right-hand side of == to avoid globbing. So
substr=$(cut -c 4-7 "${NAME}")
if [[ John == "$substr" ]]; then
And then to avoid needing duplicate if ...; then lines you could do better with a case statement:
substr=$(cut -c 4-7 "${NAME}")
case $substr in
John)
Do something
;;
Dana)
Do something else
;;
esac
Your script has many problems and you don't need cut. Use it this way:
while read -r line; do
if [[ "${line:3:4}" == "John" ]]; then
Do Something ...
elif [[ "${line:3:4}" == "Dana" ]]; then
Do Something...
fi
done < LISTS_NAME
In BASH "${line:3:3}" is same as cut -c 4-7
EDIT: If you don't want precise string matching then you can use:
while read -r line; do
if [[ "${line:3}" == "John"* ]]; then
Do Something ...
elif [[ "${line:3}" == "Dana"* ]]; then
Do Something...
fi
done < LISTS_NAME

filename match based on a known file name

I want a user to input the filename which could be reside at any location but the name of the file is fixed in end .i.e. abc. txt
Let suppose the the user inputs the file name as /usr/test/abc.txt which comes in second positional parameter in my script
I want to make below statement as true how can I achieve this
if [ $2 == ..../abc.txt ]
Thanks,
Ruchir
Let suppose the the user inputs the file name as /usr/test/abc.txt which comes in second positional parameter in my script
I want to make below statement as true how can I achieve this
Use this if condition using shell glob:
if [[ "/$2" == *"/abc.txt" ]]; then
echo "valid match"
fi
You can use basename to get the last component of the filename.
prompt> cat foo.sh
#!/bin/sh
if [ "abc.txt" == `basename $2` ]; then
echo "found .../abc.txt"
fi
prompt> foo.sh foo /a/b/c/abc.txt
found .../abc/txt
you could do:
if ( echo "$2" | grep 'abc.txt$' >/dev/null ) ; then ... ; else .... ; fi
or
if ( echo "$2" | grep '/abc.txt$' >/dev/null ) ; then ... ; else .... ; fi
(if you need that "/" too ?)
if [[ $2 == *"/abc.txt" ]]; then
echo "It ends with abc.txt";
fi
Why [[ ]] works compared to [ ] is explained here...
"[ ]" vs. "[[ ]]" in Bash shell

echo new line to terminal only when current terminal line is not empty

In bash, I would like to conditionally echo a new line depending on whether the current line in the terminal is empty or not.
Say, for example, first.sh runs first but I don't control it and I don't know what it will print each time. Can I get second.sh to start printing always on a brand new line and don't leave any blank lines above it?
first.sh
#!/bin/bash
let "n = 1"
max=$((RANDOM%3))
while [ "$n" -le "$max" ]
do
printf "%s" x
let "n += 1"
done
second.sh
#!/bin/bash
#if [ not_in_first_terminal_column ]
# echo
#fi
echo "Hola"
I want one of the following outputs
$ ./first.sh && ./second.sh
Hola
$ ./first.sh && ./second.sh
x
Hola
$ ./first.sh && ./second.sh
xx
Hola
but not
$ ./first.sh && ./second.sh
Hola
$ ./first.sh && ./second.sh
xHola
$ ./first.sh && ./second.sh
xxHola
Is it possible to do what I want? I figured using ANSI escape codes, something like in here, but I haven't found a way.
Test your variable's value if it's not empty with -n:
[[ -n $VAR ]] && echo "$VAR"
# POSIX or Original sh compatible:
[ -n "$VAR" ] && echo "$VAR"
# With if:
if [[ -n $VAR ]]; then
echo "$VAR"
fi
if [ -n "$VAR" ]; then
echo "$VAR"
fi
It's actually equivalent to [[ $VAR != "" ]] or ! [ "$VAR" = "" ].
Furthermore in Bash you can test it if it's only filled with whitespaces:
shopt -s extglob ## Place this somewhere at the start of the script
[[ $VAR == +([[:space:]]) ]] && echo "$VAR"
if [[ $VAR == +([[:space:]]) ]]; then
echo "$VAR"
fi
Use [[:blank:]] to only match spaces and tabs and not newlines and the likes if it's more helpful.
If you want to remove empty lines from input file or pipe you can use other tools like sed:
sed -ne '/^$/!p' file or ... | sed -ne '/^[[:space:]]*$/!p'

Bash, test for presence of two files

I found this answer which works fine, but I wanted to understand why the following code won't detect the presence of two files?
if [[ $(test -e ./file1 && test -e ./file2) ]]; then
echo "yep"
else
echo "nope"
fi
Running this directly from the shell works as expected:
test -e ./file1 && test -e ./file2 && echo yes
The output of test -e ./file1 && test -e ./file2 is an empty string, which causes [[ ]] to produce a non-zero exit code. You want
if [[ -e ./file1 && -e ./file2 ]]; then
echo "yep"
else
echo "nope"
fi
[[ ... ]] is a replacement for [ ... ] or test ..., not a wrapper around it.
if executes a program (or builtin, in the case of [[) and branches based on its return value. You need to omit either the [[ ]] or the tests:
if [[ -e ./file1 && -e ./file2 ]]; then
Or
if test -e ./file1 && test -e ./file2; then

Resources