1

I get an error in my Bash shell script script.sh on this line of code:

let initialLines=$(grep '' "1ドル" | wc -l || true)

error is: script.sh: line 146: let: initialLines=: syntax error: operand expected (error token is "=")

What is syntactically incorrect here?

asked Jan 23, 2017 at 2:32
3
  • 1
    Not an error, but since every string will match the empty regular expression, your grep command is equivalent to cat "1ドル", in which case you could simply run wc -l "1ドル". Commented Jan 23, 2017 at 3:01
  • 1
    @chepner: Good point, but it should be wc -l < "1ドル" (note the <), so as to prevent wc from outputting the input filename as well. Commented Jan 23, 2017 at 3:03
  • 1
    @mklement0 Details, details :) I suspect the the regular expression is wrong anyway, which means the pipeline is still relevant. (Although grep -c could be used instead as well.) Commented Jan 23, 2017 at 3:05

2 Answers 2

4

tl;dr:

Double-quote your command substitution:

let initialLines="$(grep '' "1ドル" | wc -l || true)"

That said, as explained in chepner's helpful answer, you could just use a simple assignment without needing to double-quote the RHS, although to get the same outcome as with let here, be sure to declare the variable with -i first; e.g., declare -i initialLines


It looks like the RHS of your assignment - the command substitution ($(...)) - evaluates either to the empty string or a whitespace-prefixed string in the course of the shell expansions that happen before the command is executed, so that bash ends up trying to parse one of the following commands:

let initialLines=
let initialLines= 2

If you try these in isolation, you'll get the syntax error you've experienced.


The most likely explanation is that you're using BSD wc, such as on macOS, which outputs the line count requested with -l with leading whitespace.


A simple fix is to double-quote the command substitution:

let initialLines="$(grep '' "1ドル" | wc -l || true)"

As for the command in your command substitution (it may just be an example, but it's worth commenting on):

  • grep '' will always return all input lines, so it's nothing more than a less efficient cat.

  • There is no point in using || true:

    • The exit code of the subshell in which the command substitution runs is not relevant, even with set -e in effect.

    • Also, by using true as the alternative command, you'll break the let command as well, because builtin true has no stdout output.

  • In summary, your entire command substitution could be reduced to wc -l < "1ドル".

answered Jan 23, 2017 at 2:40
1
  • 1
    Yes this did get rid of the error and I am using macOS so very knowledgeable answer Commented Jan 23, 2017 at 3:33
2

There is little or no need to use the let command here.

initialLines=$(grep '' "1ドル" | wc -l)

This solves the problem (the command substitution producing an empty or white-space prefixed string) pointed out by @mklement0 in a different way; unlike the argument to the let command, the value on the right-hand side of an assignment is not subject to word-splitting.

answered Jan 23, 2017 at 3:01
1
  • While good advice in general, there is a subtlety to consider here: to really make the two commands equivalent, you must declare initialLines with -i first, otherwise just initialLines=$(grep '' "1ドル" | wc -l) will retain leading whitespace, such as the one output by wc -l on macOS. Commented Jan 23, 2017 at 3:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.