4

First I made a file called telephone containing:

Jan;032569874    
Annemie;014588529    
Hans;015253694    
Stefaan;011802367

And what I now need to do is make a script where the user inputs a name and the output should look like,

The phone number of Jan is 032569874

I tried a lot of things but nothing worked like its supposed to do. I know its a very easy one but I just can't get it.

Ok guys those answers are clearly from a higher level. This is what I got:

#!/bin/bash
#Solution script2

IFS=";"

echo "Whose phone number do you want to know?"
read name
read name number <$1
echo "The phone number of $name is $number."
6

Here's a roughly modified version of your script:

$ more cmd.bash 
#!/bin/bash

echo "Whose phone number do you want to know?"
read name
number=$(grep "$name" telephone | cut -d';' -f2)
echo ''
echo "The phone number of $name is $number."

It works as follows:

$ ./cmd.bash 
Whose phone number do you want to know?
Hans

The phone number of Hans is 015253694.

How it works

It simply takes in the name via the read name command and stores what was typed in the variable, $name. We then grep through the file telephone and then use cut to split the resulting line from the file telephone into 2 fields, using the semicolon as the separation character. The phone number, filed 2, is stored in the variable $number.

Testing

You can use the following script to test that your script works, using the data from the file telephone.

$ while read -r i ;do 
    echo "-----"
    echo "Test \"$i\""
    ./cmd.bash <<<$i
    echo "-----"
  done < <(cut -d';' -f1 telephone)

The above commands read in the contents of the file telephone, split it on the semicolon, ;, and then takes each value from field 1 (then names) and loops through them 1 at a time. Each name is then passed to your script, cmd.bash, via STDIN, aka. <<<$i. This simulates a user typing in each of the names.

$ while read -r i ;do echo "-----"; echo "Test \"$i\""; \
    ./cmd.bash <<<$i; echo "-----"; done < <(cut -d';' -f1 telephone)
-----
Test "Jan"
Whose phone number do you want to know?

The phone number of Jan is 032569874.
-----
-----
Test "Annemie"
Whose phone number do you want to know?

The phone number of Annemie is 014588529.
-----
-----
Test "Hans"
Whose phone number do you want to know?

The phone number of Hans is 015253694.
-----
-----
Test "Stefaan"
Whose phone number do you want to know?

The phone number of Stefaan is 011802367.
-----
6

Using awk:

#!/usr/bin/awk -f
BEGIN { FS=";" } $1 ~ name { print "The number of " name " is " $2 }
phones -v name=Jan telephone                                      
The number of Jan is 032569874
2
name="jan"
line="$(grep -i ^"$name" file)"
if [ -n "$line" ]; then
  number="${line#*;}"
  echo "The phone number of ${name} is ${number}"
else
  echo "There is no phone number for ${name}."
fi 
1

A simple one-liner:

read name; grep $name telephone | awk -F ';' '{print "The phone number of "$1" is "$2}'

Example usage:

Jan
The phone number of Jan is 032569874
  • read reads the input into a variable called name. The input is accepted after read receives a newline or carriage return (e.g. pressing Enter).

  • grep searches the telephone file for the input stored in name, returning a single line assuming the name only occurs once.

  • awk is asked to use a semicolon (;) as the field delimiter via the -F ';' parameter. The semicolon is in quotes to prevent the shell from interpreting it.

  • The awk program {print "The phone number of "$1" is "$2} prints the desired text while substituting $1 and $2 with their respective fields obtained from the line piped in from grep.

You can store this line in your .sh file and run it as a script.

  • 1
    awk does pattern matching, so the grep is redundant (and the pipe an overhead)... – jasonwryan Nov 22 '14 at 19:00
1

I used grep command with \k notify and lookbehind assertion:

$ read name; echo "The phone number of $name is $(grep -oP "$name;\K.*" telephone)"
  Jan                                  #Input
  The phone number of Jan is 032569874 #Output

grep with -P(perl-regexp) parameter supports \K, which use to ignoring the previously matched characters(ignore name and semicolon;).

-o, --only-matching: print only the matched (non-empty) parts of a matching line.

$(command) "Command Substitution" that allows the output of a command to replace the command name.

Or you can use the lookbehind assertion in place of nifty \K.

$ read name; echo "The phone number of $name is $(grep -oP "(?<=$name;).*" telephone)"
1

With sed:

sed 's|.*|s/\\(&\\);\\([0-9]*\\).*/\\1'\''s phone # is \\2./p|;q' </dev/tty|
sed -nf - /dev/fd/3 3<<\IN
Jan;032569874 
Annemie;014588529 
Hans;015253694 
Stefaan;011802367
IN

The first sed reads a line of input from the terminal and converts it to a working s/// substitution statement for the second sed. There's nothing fancy here - as is it will break if you give it / on input for example, but, basically, it works:

OUTPUT

#I typed the line below then ENTER
Annemie
Annemie's phone # is 014588529.

You'll probably want to do sed -nf - phonefilename rather than the /dev/fd/3 I used for the filename to demonstrate. And in that case you won't need the <<IN...IN heredoc bit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.