Bash:在意外令牌“else”附近出现语法错误

时间:2022-07-14 23:03:29

I have the following code that checks whether either of two input args are supplied, and depending on their existance runs a certain piece of code. I'm running into syntax errors in my if statements however, because I'm getting an unexpected token `else' error

我有以下代码检查是否提供了两个输入args,并根据它们的存在运行特定的代码段。我在if语句中遇到了语法错误,因为我得到了一个意外的令牌“else”错误

if [ -z "${4}" ] || [ -z "${5}" ]
then
    echo "Missing index argument(s). Defaulting to entire file."
    cat ${devicesFile} | cut -d "," -f 4 | tr [:upper:] [:lower:] | awk '{print substr($1,1,8)"-"substr($1,9,4)"-"substr($1,13,4)"-"substr($1,17,4)"-"substr($1,21,12)}' | while read deviceGuid
else
    i1=${4}
    i2=${5}
    head -n ${i1} ${devicesFile} | tail -n ${i2} | cut -d "," -f 4 | tr [:upper:] [:lower:] | awk '{print substr($1,1,8)"-"substr($1,9,4)"-"substr($1,13,4)"-"substr($1,17,4)"-"substr($1,21,12)}' | while read deviceGuid
fi

Is it an issue with my or condition.? That's the only thing I can really think of. Any help would be greatly appreciated.

这与我的条件有关吗?这是我唯一能想到的。如有任何帮助,我们将不胜感激。

//Here's what I had before I tried to add the index parameters, so what HVD said about the broken while makes sense..

//这是我在添加索引参数之前所得到的,所以HVD关于破损的说法是有道理的。

cat ${devicesFile}  | cut -d "," -f 4 | tr [:upper:] [:lower:] | awk '{print substr($1,1,8)"-"substr($1,9,4)"-"substr($1,13,4)"-"substr($1,17,4)"-"substr($1,21,12)}' | while read deviceGuid
do
    # now=`date +"%Y%m%d %H%M%S"`
    currentTime=`date +"%H%M%S"`
    currentHour=`date +"%H"`
    currentDate=`date +"%Y%m%d"`
    # create parent directory
    mkdir -p ${crashlogFolder}/${currentDate}/${currentHour}/${crashCode}/
    # create crash log for device
    touch ${crashlogFolder}/${currentDate}/${currentHour}/${crashCode}/${currentTime}_${deviceGuid}.log
done

3 个解决方案

#1


4  

You're lacking a body to your while block, it should have the form while <condition>; do <actions>; done

你缺少一个身体到你的while块,它应该有形式,而 <条件> ; <行动> ;完成

if [[ -z "${4}" || -z "${5}" ]]; then
    # …
    cat ${devicesFile} \
    | … \
    | while read deviceGuid; do echo $deviceGuid; done
else
    # …
    head -n ${i1} ${devicesFile} \
    | … \
    | while read deviceGuid; do echo $deviceGuid; done
fi

Explaination

  1. used bash test [[ … ]] so you can use the boolean OR inside as [[ … || … ]], discard if you need portability;
  2. 使用bash测试[[…]],因此您可以使用布尔值或内部的布尔值[[…],如果您需要可移植性,则丢弃;
  3. replaced some of your command by just for clarity
  4. 为了清晰起见,用…代替你的一些命令
  5. escaped newline, \ at the end of line (no spaces must follow), to get a clearer script
  6. 避免换行,在行尾(没有空格必须跟随),以获得更清晰的脚本。
  7. added missing block with dummy echo $deviceGuid command.
  8. 添加了缺少的块与虚拟echo $deviceGuid命令。

#2


5  

You cannot mix control structures like that. If you originally had

你不能像那样混合控制结构。如果你最初

a | while b
do
  c
done

and now you want a to be customisable, you cannot do

现在你想要一个可定制的,你不能做。

if d
then
  e | while b
else
  f | while b
fi
do
  c
done

Shells just don't work like that. (Nor do most other languages.) while b; do c; done was a single statement, and cannot be broken up like that.

壳层不像这样工作。(大多数其他语言也是如此);c;done只是一个语句,不能这样分解。

Instead, you should change it to

相反,您应该将它改为

if d
then
  e
else
  f
fi | while b
do
  c
done

The whole if d; then e; else f; fi is a single statement, and its output, regardless of which of the commands it comes from, will be piped to the while statement.

如果d;然后e;其他f;fi是一个单独的语句,它的输出,不管它来自哪个命令,都将被引导到while语句。

#3


3  

This is really a comment on Édouard Lopez's answer: DRY -- pull out all the common code:

这实际上是对爱德华·洛佩兹的回答的评论:干——拿出所有的通用代码:

if [[ -z "${4}" || -z "${5}" ]]; then
    cat ${devicesFile} 
else
    head -n ${i1} ${devicesFile} | tail -n ${i2}
fi |
  cut -d "," -f 4 | 
  tr [:upper:] [:lower:] | 
  awk -F, '{print substr($1,1,8)"-"substr($1,9,4)"-"substr($1,13,4)"-"substr($1,17,4)"-"substr($1,21,12)}' |
  while read deviceGuid; do 
    : 
  done

Note to MrTunaDeluxe: ${var} is different from "$var" -- you should prefer the latter. The first form is required for array element expansion, the various parameter substitutions, and also to disambiguate the variable from surrounding text (e.g. echo "${var}text"), but just using braces will not prevent word splitting or filename expansions.

MrTunaDeluxe注意:${var}与“$var”不同——您应该更喜欢后者。第一个表单用于数组元素展开、各种参数替换,以及从周围的文本(例如echo“${var}text”)中消除变量的歧义,但是仅仅使用大括号并不会阻止单词拆分或文件名扩展。

#1


4  

You're lacking a body to your while block, it should have the form while <condition>; do <actions>; done

你缺少一个身体到你的while块,它应该有形式,而 <条件> ; <行动> ;完成

if [[ -z "${4}" || -z "${5}" ]]; then
    # …
    cat ${devicesFile} \
    | … \
    | while read deviceGuid; do echo $deviceGuid; done
else
    # …
    head -n ${i1} ${devicesFile} \
    | … \
    | while read deviceGuid; do echo $deviceGuid; done
fi

Explaination

  1. used bash test [[ … ]] so you can use the boolean OR inside as [[ … || … ]], discard if you need portability;
  2. 使用bash测试[[…]],因此您可以使用布尔值或内部的布尔值[[…],如果您需要可移植性,则丢弃;
  3. replaced some of your command by just for clarity
  4. 为了清晰起见,用…代替你的一些命令
  5. escaped newline, \ at the end of line (no spaces must follow), to get a clearer script
  6. 避免换行,在行尾(没有空格必须跟随),以获得更清晰的脚本。
  7. added missing block with dummy echo $deviceGuid command.
  8. 添加了缺少的块与虚拟echo $deviceGuid命令。

#2


5  

You cannot mix control structures like that. If you originally had

你不能像那样混合控制结构。如果你最初

a | while b
do
  c
done

and now you want a to be customisable, you cannot do

现在你想要一个可定制的,你不能做。

if d
then
  e | while b
else
  f | while b
fi
do
  c
done

Shells just don't work like that. (Nor do most other languages.) while b; do c; done was a single statement, and cannot be broken up like that.

壳层不像这样工作。(大多数其他语言也是如此);c;done只是一个语句,不能这样分解。

Instead, you should change it to

相反,您应该将它改为

if d
then
  e
else
  f
fi | while b
do
  c
done

The whole if d; then e; else f; fi is a single statement, and its output, regardless of which of the commands it comes from, will be piped to the while statement.

如果d;然后e;其他f;fi是一个单独的语句,它的输出,不管它来自哪个命令,都将被引导到while语句。

#3


3  

This is really a comment on Édouard Lopez's answer: DRY -- pull out all the common code:

这实际上是对爱德华·洛佩兹的回答的评论:干——拿出所有的通用代码:

if [[ -z "${4}" || -z "${5}" ]]; then
    cat ${devicesFile} 
else
    head -n ${i1} ${devicesFile} | tail -n ${i2}
fi |
  cut -d "," -f 4 | 
  tr [:upper:] [:lower:] | 
  awk -F, '{print substr($1,1,8)"-"substr($1,9,4)"-"substr($1,13,4)"-"substr($1,17,4)"-"substr($1,21,12)}' |
  while read deviceGuid; do 
    : 
  done

Note to MrTunaDeluxe: ${var} is different from "$var" -- you should prefer the latter. The first form is required for array element expansion, the various parameter substitutions, and also to disambiguate the variable from surrounding text (e.g. echo "${var}text"), but just using braces will not prevent word splitting or filename expansions.

MrTunaDeluxe注意:${var}与“$var”不同——您应该更喜欢后者。第一个表单用于数组元素展开、各种参数替换,以及从周围的文本(例如echo“${var}text”)中消除变量的歧义,但是仅仅使用大括号并不会阻止单词拆分或文件名扩展。