How To Make CASE Statement To Iterate Over All Patterns Even When A Match Is Found - case

How do I make the case command below to continue matching the next pattern even after it matches "apple" without jumping to the end of the case flow
#!/bin/sh
FRUIT="apple"
case "$FRUIT" in
"apple") echo "Apple pie is quite tasty."
;;
"banana") echo "I like banana nut bread."
;;
"kiwi") echo "New Zealand is famous for kiwi."
;;
esac

I have found the answer to my question through experiment. I just changed ;; to ;;& and it worked!

Related

UNIX: How to print contents of variable with formatting.

I just want to print ls -l the same way it looks from the command line (each file on a new line). I have looked every where for a solution and know my solution should work but for some reason it doesn't. I have tried:
#!/bin/csh
set list = `ls -l`
echo "$list"
and:
#!/bin/csh
set list = "`ls -l`"
echo "$list"
with no luck. What I really want to do is use grep on ls -l later (so maby I'm going about this wrong), but I can't because it prints list as one long line.
(and yes, I have to use csh)
I don't know how to get around csh's behaviour of joining words together when you echo, but you may be able to use array-like functionality and a loop. For example:
#!/bin/csh
set list=( "`printf 'a\nb\nc\n'`" )
echo "count=$#list"
echo "2 = $list[2]"
echo
set n=0
while ( $n < $#list )
# n += 1
echo "$n : $list[$n]"
end
Which for me produces the output:
count=3
2 = b
1 : a
2 : b
3 : c
Note that I'm using tcsh on FreeBSD. Your csh may be different, you haven't mentioned your platform.
To bring this back to your list of files question, you can replicate the output you're looking for with a similar loop:
#!/bin/csh
set list=( "`ls -l`" )
set n=0
while ( $n < $#list )
# n += 1
echo "$list[$n]"
end
The important consideration here is that within (command substitution) backquotes (`...`), output is word-separated by whitespace, whereas inside double quotes ("..."), output is word-separated by newlines.
That said...
What I really want to do is use grep on ls -l later (so maby I'm going about this wrong), but I can't because it prints list as one long line.
Entirely possible! :-) But without a full understanding of the underlying problem you're trying to solve, helping you achieve your solution is the best we can do. Beware the dreaded XY Problem.

Grep statement in If-Then-Else Statment is not giving intended results

The intended result of this program is to perform the deletion of a record from a temporary file by searching for the last name. If the name is in the file it will display a message that the record is deleted from the file. The message will have a last and first name of the person deleted. If there is no record for the name entered, display an error message indicating that the name is not in the file. The error message will have the last name of the person searched.
For the most part I have figured this code completely out. However, I am running into errors that are giving me a lot of trouble.
Code is as follows:
#While loop
delete_choice="y"
until [[ $delete_choice == "n" ]]
do
#Create Delete Message
clear
echo " Delete Record "
echo -en '\n'
echo -en '\n'
echo "What is the last name of the person you want to delete:"
read last_name
if line=$( grep -Fi "$last_name" "$2")
then
IFS=: read c1 c2 rest <<< "$line"
echo -e "Last Name: $c1\nFirst Name: $c2\nSTUDENT RECORD HAS BEEN DELETED FROM FILE"
sed "/$line/d" $2
else
echo "ERROR: $last_name is not in database"
echo "Would you like to search again (y/n)"
read delete_choice
fi
done
;;
So what happens when I execute this code is it brings up the delete message and asks me to input a last name. I put in a last name "smith", when I do this it skips the whole if statement and goes right to the end of the loop and then brings me right up to asking me what the last name is of the person I want to delete. So obviously it is concentrated in the grep statement somewhere. Another odd thing is if I put a name that I know is not in there it will take me to the else statement and give me the error message and ask me if I want to search again.
Any help would be appreciated, I been searching for hours with the grep statement and cannot figure it out.
Additionally: On a side note does anybody know how to make it so I can input "n" or "N" in the Until...Do statement to keep the loop going?
EDIT:
Ok I fixed all the other problems in this code but there is just one problem I cannot fix. Every time I delete an entry from the file it doesn't allow me to execute the echo command.
Code is as follows:
d|D)
#While loop
delete_choice="y"
while true
do
#Create Delete Message
clear
echo " Delete Record "
echo -en '\n'
echo -en '\n'
echo "What is the last name of the person you want to delete:"
read last_name
if line=$(grep -i "^${last_name}:" "$2")
then
echo "$line" |
while IFS=: read c1 c2 rest; do
last=$c1
first=$c2
sed -i "/^$c1:$c2:/d" "$2"
done
echo -e "Last Name: $last\nFirst Name: $first\nSTUDENT RECORD HAS BEEN DELETED FROM FILE"
else
echo "ERROR: $last_name is not in database"
echo "Would you like to search again (y/n):"
read delete_choice
case $delete_choice in [Nn]) break;; esac
fi
done
;;
As you can see I execute the echo command but it never displays. However, I can tell that it deletes the entry from the file when I exit the program and check it. Does anybody know how to make it display the echo command correctly?
You have used <<< which is a Bash-only feature.
The proper way to debug your problem is to run your script with ksh -x script arg (or possibly sh -x script arg if your script was a pure Bourne shell script; but this one isn't).
However, you have some peculiarities in your code. Allow me to offer a refactoring.
delete_choice="y"
until [[ "$delete_choice" == "n" ]]
do # Indent your control structures
clear
echo " Delete Record"
echo # Massive trailing whitespace removed ----------^^^
echo # Just echo to output a new line
echo "What is the last name of the person you want to delete:"
read last_name
case $last_name in [Nn]) break;; esac # Exit on "n"
if line=$(grep -Fi "$last_name" "$2")
then # Indent your control structures
file=$2
oldIFS=$IFS
IFS=:
set -- "$line" # break input into $1, $2, etc
IFS=$oldIFS
echo -e "Last Name: $1\nFirst Name: $2\nI SCREAM IN UPPER CASE"
sed -i "/^$1:$2:/d" "$file" # note quoting and -i and changed variable
else
echo "ERROR: $last_name is not in database"
echo "Would you like to search again (y/n)"
read delete_choice
fi
done
Another problem here was unrelated to your question. Directly executing the user's input in the regex would be extremely careless -- what if somebody input just a for a last name? The changed code will only delete one user, regardless of how short the input; but perhaps the grep should also be anchored to use a tighter search expression.
There is still a possibility that a peculiar name in the database would not match itself, or match more than itself. For example, I use my second given name, so where my full name is required, I often input my name as "First *Middle Last" with an asterisk next to the name I use, which is the convention where I live; but the string *Middle will not match itself in a regular expression.
Also, without -i, the sed script would simply print a copy of the database to standard output.
The delete_choice variable is not getting updated anywhere within your code so you could change the exterior loop to just while true and handle exiting by breaking out of the loop, like I have done. I didn't change the until on the vague speculation that this might be used in other parts of your code which you aren't showing.

If I want to list multiple variables in one 'if' command in unix, how would I do it? [Beginner]

so I have a really basic question here which I'm sure any experienced user can answer quickly! I'm just not too sure what to search to find the answer!
So lets say I was write an 'if' command in a shellscript and I wanted to essentially say:
If test variableA AND variableB AND variableC AND variableD -eq 1 ; then
echo "Bye bye"
fi
so basically I'm not sure what to replace the AND's with in UNIX? Do I just write variableA, variableB, variableC, variableD or do I have to list them out in brackets or do I just leave spaces infront of them?
Thanks in advance!
(Also as a bonus question, what if I want to replace the AND with the OR in the example above? How would that translate in UNIX?)
-a is the AND operator in test:
if [ -n "$variableA" -a -n "$variableB" -a -n "$variableC" -a "$variableD" -eq 1 ]
then
echo "Bye bye"
fi
If you want OR, the operator is -o. These are both in the test man page.

How to pass a slice of arguments to a command in zsh?

I have this function:
find () {
case "$1" in
package)
pacman -Ss
;;
file)
echo "Find file"
;;
*)
echo "You cannot find something like this."
;;
esac
}
My goal is to be able to do simething like find package foo. However it looks like the the foo is not passed as argument to pacman. How can I fix that?
Came up with the following simple solution for a variant amount of given arguments, let's say you want to slice the first two strings out.
So, say you were taking in some arguments and you know how many arguments you wish to exclude, you can slice it up like this
#!/bin/bash
array=${#: (($#-2)),-1}
for element in $array; do
echo $element
done
An example of using this, where the -2 in (($#-2)) is the number of arguments you wish to exclude from the beginning.
$ ./script.sh some arguments given to the script
$ given
$ to
$ the
$ script
Oh, I'm using zsh btw, so - apologies if there's something in there unsupported. don't think so.
This is what you need then. Try this:
find () {
case "$1" in
package)
shift
pacman -Ss $#
;;
file)
echo "Find file"
;;
*)
echo "You cannot find something like this."
;;
esac
}
Try this:
find () {
case "$1" in
package)
pacman -Ss $2
;;
file)
echo "Find file"
;;
*)
echo "You cannot find something like this."
;;
esac
}

Why does the Bourne shell printf iterate over a %s argument?

What's going on here?
printf.sh:
#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" $NAME
Command line session:
$ ./printf.sh
Hello, George
Hello, W.
Hello, Bush
UPDATE: printf "Hello, %s\n" "$NAME" works. For why I'm not using echo, consider
echo.sh:
#! /bin/sh
FILE="C:\tmp"
echo "Filename: $FILE"
Command-line:
$ ./echo.sh
Filename: C: mp
The POSIX spec for echo says, "New applications are encouraged to use printf instead of echo" (for this and other reasons).
Your NAME variable is being substituted like this:
printf "Hello, %s\n" George W. Bush
Use this:
#! /bin/sh
NAME="George W. Bush"
printf "Hello, %s\n" "$NAME"
is there a specific reason you are using printf or would echo work for you as well?
NAME="George W. Bush"
echo "Hello, "$NAME
results in
Hello, George W. Bush
edit:
The reason it is iterating over "George W. Bush" is because the bourne shell is space delimitted. To keep using printf you have to put $NAME in double quotes
printf "Hello, %s\n" "$NAME"
The way I interpret the man page is it considers the string you pass it to be an argument; if your string has spaces it thinks you are passing multiple arguments. I believe ColinYounger is correct by surrounding the variable with quotes, which forces the shell to interpret the string as a single argument.
An alternative might be to let printf expand the variable:
printf "Hello, $NAME."
The links are for bash, but I am pretty sure the same holds for sh.
If you want all of those words to be printed out on their own, use print instead of printf
printf takes the formatting specification and applies it to each argument that you pass in. Since you have three arguments {George, W., Bush}, it outputs the string three times using the different arguments.

Resources