sh: syntax error near unexpected token `<' - bash

I am creating a script where I am redirecting the output of an awk command into a loop, but it's giving me this error:
sh: -c: line 3: syntax error near unexpected token `<'
sh: -c: line 3: `done < <(awk "{print}" inputfile.txt)'
I was able to run it against a different remote host, but this host is giving me an error. Does anyone know if some versions of sh/bash don't support that syntax, or know any alternatives to that syntax, or maybe spot a bug that I haven't been able to see? (I'm new to bash scripting, so even a point in the right direction would be helpful!)
Here is a pared-down version of my script that I was able to reproduce the issue on:
#!/usr/bin/env bash
host=$1
ssh $host 'while read line
do
echo "hi";
done < <(awk "{print}" inputfile.txt)'

It looks like the remote user on that host uses a shell that's not Bash to run the command, see this Q&A; a way around that is to either avoid Bashisms:
ssh "$host" 'awk "{print}" inputfile.txt \
| while IFS= read -r line; do
echo "$line"
done'
which comes with its own pitfalls, see A variable modified inside a while loop is not remembered – alternatively, you could specify that the remote host should run Bash:
ssh "$host" <<'EOF'
bash -c 'while IFS= read -r line; do
echo "$line"
done < <(awk "{print}" inputfile.txt)'
EOF

Related

Bash script working locally but returning syntax error in CI

On my gitlab CI I am running the following simple script (.gitlab-ci.yml):
STR=$(cat $FILE)
if grep -q "substring" <<< "$STR"; then echo "ok"; fi
Unfortunatley this gives me the error
/bin/sh: eval: line 100: syntax error: unexpected redirection
Running the same command locally as a script is working as expected:
#!/bin/sh
FILE="./file.txt"
STR=$(cat $FILE)
if grep -q "substring" <<< "$STR"; then
echo "ok"
fi
The file has the content:
This has a substring somewhere
/bin/sh is not bash and <<< is a bash extension not available on every shell. Install bash, change shebang to /bin/bash and make sure the script is run under bash or use posix compatible syntax printf "%s\n" "$str" | grep...
Note: UPPER CASE VARIABLES are by convention reserved for exported variables, like IFS COLUMNS PWD UID EUID LINES etc. Use lower case variables in your scripts.

Errors in bash scripts

I have a couple of errors in my script which I built in CentOS then deployed to Unix. I have the shebang #!/bin/bash on top of my scripts and execute my script using bash myscript.sh
LINE in script:
existing[0]=""
ERROR: existing[0]=: not found
LINE in script: not sure if its this -
while IFS='' read -r line || [[ -n "$line" ]]; do
or this one -
if [[ $sftp_status != 0 ]]; then
ERROR: syntax error at line 118: `i=$' unexpected
LINE in script:
i=$((i + 1))
if you have the shebang line on top, you can set the execute permission and run the script as ./<scriptname>. You dont need the bash <scriptname>.
Those syntax seems to valid to me and i will doubt if this is bash. Try /bin/bash <scriptname> and see if it helps.

Bash functions inside process substitution

Getting an error trying to call a function inside a process substitution.
Is there any way to do this?
#!/bin/bash
function testfunc
{
echo "bork"
}
diff <(testfunc) <(echo "bork")
The error is:
bork.sh: line 7: syntax error near unexpected token `('
bork.sh: line 7: `diff <(testfunc) <(echo "bork")'
--Update--
Problem was calling sh bork.sh, instead of bash ./bork.sh . Moral of the story make sure which shell you are executing with.
There's no problem here:
$ chmod +x test.sh
$ ./test.sh
Clear diff. No problem!
$ bash -x ./test.sh
+ diff /dev/fd/63 /dev/fd/62
++ testfunc
++ echo bork
++ echo bork
Proof that it worked
Troubleshooting:
Maybe you
run in a restricted shell
you don't have /dev/fd available/mounted correctly (due to somekind of secure chroot jail?)
The problem is probably that you're running the command with sh instead of bash.
$ cat > xx.sh
#!/bin/bash
function testfunc
{
echo "bork"
}
diff <(testfunc) <(echo "bork")
$ sh xx.sh
xx.sh: line 7: syntax error near unexpected token `('
xx.sh: line 7: `diff <(testfunc) <(echo "bork")'
$ bash xx.sh
$
The process substitution is not portable to the shell in /bin/sh. See the Bash manual on POSIX mode and bullet 28:
Process substitution is not available.
Tested on Mac OS X 10.10.5 (Yosemite).

bash cat a file from a another server to a variable

i am trying to do a basic command of cat to a variable and it does not work..
lines="not working"
sshpass -p triltest ssh root#ILCFS 'cat /var/try/check ' > $lines
echo $lines
./script.sh: line 34: $lines: ambiguous redirect
not working
the file exists. can anyone help me please?
Use `command` or $(command). I.e.
lines=$(sshpass -p triltest ssh root#ILCFS 'cat /var/try/check ')
echo "$lines"

Why do I get errors when using > > in bash?

I've been looking up some bash stuff today and a few snippets I've tried have included > > which seems to be the cause of the errors I'm receiving.
Example snippet:
command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)
Here's what I'm working with.
$ bash --help
GNU bash, version 3.2.48(1)-release-(x86_64-apple-darwin12)
EDIT
Here are the errors I'm gettting:
file.sh: line 14: syntax error near unexpected token `>'
file.sh: line 14: `command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)'
According to the answers to this question, Bash 3.2.48 for Mac OS X has some limitations when it comes to process-substitution; it supports it in some cases but not others. Your case is apparently one where it doesn't.
Quoting from the best/most-helpful answer there:
The one from macports (4.2.37 — normally /opt/local/bin/bash if you have it installed) works fine. […] Perhaps you may want to use macports bash for this script.
The most naive way to solve your problem is the following:
while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done < <( { command > /dev/null ; } 2>&1 )
We're sending all stdout of command to /dev/null and then then redirecting the stderr to stdin.
Or the other way round:
{ command > /dev/null ; } 2>&1 | while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done
With these methods you don't have to play too much with file descriptors!
Done.

Resources