8
votes

I have syntax error near unexpected token & in next : in bash scripts its'go like this :

#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null)|& grep real|awk '{print $2}'`

when i issue this command on cli i get good output, problem is when invoke this in script i can get any output from var1

./check_cdifonline.sh: command substitution: line 2: syntax error near unexpected token `&'
./check_cdifonline.sh: command substitution: line 2: `(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null) | & grep real | awk '{print $2}''
3
Why are you &ing the grep? You're already piping the output to grep. - admdrew
Because i need to parse real value from time command and you need to send to stderr first to get output from time, it's not possible - klerk
Your question has been edited to fix the formatting, but there are still a few dangling characters at the end of the first code block. You can fix that by editing your question, deleting the first code block and replacing it by a copy-and-paste of your actual code, then selecting the block and clicking the {} to format it as code (which just indents it 4 columns). - Keith Thompson

3 Answers

11
votes

You can use the sequence |& to pipe both stdout and stderr from one process to another.

You cannot have a space between the | and the &. (csh and tcsh allow a space; bash does not.) I suspect you happen to be typing it without the space when you run the command interactively; the syntax is the same either way.

This:

foo |& bar

is shorthand for this:

foo 2>&1 | bar

UPDATE :

With bash 3.2.25, the |& token is not recognized; was added as a new feature in bash 4.1. Running your script with the older bash, I get the same error message you do.

To make your script compatible with older versions of bash, just do the equivalent redirection without using the |& operator:

#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`

Further refinements: Use $(...) rather than `...`:

#!/bin/bash
var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}')

You can also incorporate the grep search into the awk command:

#!/bin/bash
var1=$((/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | awk '/real/ {print $2}')

Warning: I have not thoroughly tested these beyond verifying that they run without syntax errors.

I still see no difference between |& and | &. Is it possible that /bin/bash is a different version than what you're running interactively? Try /bin/bash --version and echo $BASH_VERSION.

0
votes

Try change to:

var1=$(/usr/bin/time cdifonline -CD 186821 -ALL >/dev/null | awk '/real/ {print $2}')
0
votes

Thanks Keith I have no problems anymore you saved my day :) so the bash version was the problem and with avoiding of & I have no errors, thanks also for fine tuning :)

so this works with my bash version

#!/bin/bash
var1=`(/usr/bin/time cdifonline -CD 186821 -ALL > /dev/null) 2>&1 | grep real | awk '{print $2}'`