LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-24-2010, 10:38 AM   #1
phonebooth
LQ Newbie
 
Registered: Jul 2006
Location: mariposa ca
Distribution: Fedora
Posts: 12

Rep: Reputation: 0
bash script and awk


Below is the part of my bash script which uses awk to to fetch a line from a file. Choice is set by a case, and i know it is receiving a proper number because of the echo statement. The problem is with the syntax of the awk command it says the error is with one of the ', but when I run the command at the command line and replace "$choice" with a number it works properly. So I am not sure what is going on.

echo "announcing choice $choice"
command="awk 'NR = "$choice"' beerpong.txt | say"
$command


Thanks for the help
 
Old 03-24-2010, 10:46 AM   #2
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Let me ask you this, if we changed this slightly to:

command="ls"
$command

What would you expect to be the output from this?
If you answer this you will be able to figure out what is wrong, unless you have skipped some of the code?
 
Old 03-24-2010, 10:47 AM   #3
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
The pipe symbol in $command will not be actioned because bash parses for pipelines before expanding variables.

You could get around this by using eval but it would be messy regards double parsing the quotes so easier to go with
Code:
echo "announcing choice $choice"
command="awk 'NR = "$choice"' beerpong.txt"
$command | say
 
Old 03-24-2010, 10:48 AM   #4
slinx
Member
 
Registered: Apr 2008
Location: Cleveland, Ohio
Distribution: SuSE, CentOS, Fedora, Ubuntu
Posts: 106

Rep: Reputation: 23
Quote:
Originally Posted by phonebooth View Post
Below is the part of my bash script which uses awk to to fetch a line from a file. Choice is set by a case, and i know it is receiving a proper number because of the echo statement. The problem is with the syntax of the awk command it says the error is with one of the ', but when I run the command at the command line and replace "$choice" with a number it works properly. So I am not sure what is going on.

Code:
        echo "announcing choice $choice"
        command="awk 'NR = "$choice"' beerpong.txt | say"
        $command

Thanks for the help
The single quotes prevent expansion of shell variables. Try this:

Code:
        echo "announcing choice $choice"
        command="awk -vchoice=$choice 'NR = "choice"' beerpong.txt | say"
        eval $command
It would help to explain what you are trying to accomplish...

Last edited by slinx; 03-24-2010 at 10:52 AM.
 
Old 03-26-2010, 10:07 AM   #5
phonebooth
LQ Newbie
 
Registered: Jul 2006
Location: mariposa ca
Distribution: Fedora
Posts: 12

Original Poster
Rep: Reputation: 0
The only method I could kinda get to work was slinx's although instead of reading a single line it reads the entire file. The script takes an input from the user and then translastes the corresponding input into a line number (the line number refers to a second file). The script should read that line and pipe it to the say command so the computer will speak it.

Here is the entire script.

Code:
#!/bin/bash 
 input=a

while [ "$input" != "qq" ]
do
        read input

        case "$input" in
        "b" | "B")
          choice=1;;
        "i" | "I")
          choice=2;;
        "d" | "D")
           choice=3;;
        "t" | "T")
         choice=4;;
        "s" | "S")
          choice=5;;
        "y" | "Y")
          choice=6;;
        "h" | "H")
          choice=7;;
        "t" | "T")
          choice=8;;
        "l" | "L")
          choice=9;;
        "r" | "R" )
          choice=10;;
        "g" | "G")
          choice=11;;

        esac

        echo "announcing choice $choice"
        command="awk -v choice=$choice 'NR = "choice"' beerpong.txt"
        eval $command | say
done
exit 0
 
Old 03-26-2010, 10:13 AM   #6
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by phonebooth View Post
The only method I could kinda get to work was slinx's ...
Please post the output when trying my suggestion.
 
Old 03-26-2010, 10:41 AM   #7
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,005

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
@catkin Am I missing something or should yours at least have an echo at the front of the last line:

Quote:
echo $command | say
 
Old 03-26-2010, 02:54 PM   #8
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by grail View Post
@catkin Am I missing something or should yours at least have an echo at the front of the last line:
Maybe! I was guessing from the OP's
Code:
command="awk 'NR = "$choice"' beerpong.txt | say"
that the intention was for awk to print line number $choice from beerpong.txt to stdout and the say command would take it from standard in and do ... whatever say does.
 
Old 03-27-2010, 12:51 AM   #9
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
First an analysis of what bash does with
Code:
command="awk 'NR = "$choice"' beerpong.txt | say"
$command
The steps taken by bash are given here where it says:

... the shell does the following:
  1. [snip]
  2. Breaks the input into words and operators, obeying the quoting rules described in Quoting. These tokens are separated by metacharacters. Alias expansion ... [snip].
  3. Parses the tokens into simple and compound commands (see Shell Commands).
  4. Performs the various shell expansions (see Shell Expansions), breaking the expanded tokens into lists of filenames (see Filename Expansion) and commands and arguments.
  5. Performs any necessary redirections ... [snip]
  6. Executes the command
  7. [snip]

Assuming the value of $choice is 4 and no aliases apply then the value of $command is
Code:
awk 'NR = 4' beerpong.txt | say
When the second line of the code snippet is run by bash, this is what bash does
  1. [snip]
  2. Examines the command (line) and finds a single token (word-or-operator) that is a word. The command is unchanged; it is still $command.
  3. Examines the command for
    1. Pipelines identified by "|"
    2. Lists identified by ";", "&", "&&" or "||"
    3. Compound commands identified by "until", "while" or "for"
    4. Conditional commands identified by "if", "case", "select", "(( ))" or "[[ ]]"
    5. Grouping commands identified by "( )" or "{ }"
    6. Coprocesses identified by "coproc"
    None of the above apply. The command is unchanged; it is still $command.
  4. Expands $command. The command is now
    Code:
    awk 'NR = 4' beerpong.txt | say
  5. Looks for redirection and finds none. The command is not changed.
  6. Executes the command: runs awk with arguments
    1. 'NR = 4'
    2. beerpong.txt
    3. |
    4. say
  7. [snip]
When the awk command runs, it borks on the first argument. Note: when awk 'NR = 4' beerpong.txt is run at the command prompt it works because bash strips off the single quotes and runs awk with two arguments: NR = 4 and beerpong.txt.

How to fix?
  1. "NR = 4" can be corrected to "NR == 4"
  2. "NR == 4" can conveniently be made a single word by changing it to NR==4.
  3. Move the pipe symbol and the say command out of $command
    Code:
    command="awk NR==$choice beerpong.txt"
    $command | say
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash script is enterpreting $1, $2 values in awk script ... praveen_218 Programming 4 09-14-2009 03:38 PM
Help with BASH script and AWK and SED NickJH Linux - Newbie 11 03-07-2009 04:08 PM
Problem with AWK in a BASH script geek_man Programming 4 01-20-2008 07:16 PM
Putting awk in bash script the_imax Programming 9 05-12-2007 03:50 PM
can awk see bash script arguments ? sharapchi Programming 7 12-14-2006 08:03 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:30 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration