【问题标题】:Inconsistent syntax error in bash arithmetic expression: (error token is "integer1-integer2")bash 算术表达式中的语法错误:(错误标记为“integer1-integer2”)
【发布时间】:2014-07-01 01:00:18
【问题描述】:

我编写了一个脚本来对一些大型平面文件进行子集化,其中子集的整数个数(即 $increment)作为用户输入变量。仅当此输入参数是 odd 整数时,我才观察到一种奇怪的行为(bash 语法错误)。为了(略微)提高清晰度,我在原始 shell 脚本的精简版本中复制了这个错误行为。我无法提供平面文件,但希望有 shell/bash 专业知识的人可以通过查看代码和错误消息来诊断这里发生了什么(我已经通过http://www.shellcheck.net/ 运行了这个并且没有发现任何严重的问题) .

当 $increment 设置为偶数(例如 8)时,shell 脚本执行时不会出错,并为 while 循环的每次迭代输出所需的打印语句(参见下面的“注意”)。以下是这些打印语句的一些示例输出:

Line of interest: span2=84688
Line of interest: span2=85225
Line of interest: span2=86323
...

但是,当 $increment 为奇数时(例如 9),脚本会在第 48 行“span2=$(($line2-$last2))”处失败,并显示错误语句:

test_case.sh: line 48: 153026
153027-77419: syntax error in expression (error token is "153027-77419")

这很奇怪,因为前面的 echo print 语句输出“感兴趣的行:span2=75278”表明算术表达式正在子shell 中计算,没有错误,就在失败的行之前。所以很明显,这里减去的整数没有什么特别之处,但奇怪的是,例如,当表达式参数 $line2 等于“ 153027"。不过,我不确定这是否/如何与语法错误相关。

#!/bin/bash
set -e


increment=9
file1="path/to/file1"
file2="path/to/file2"
file3="path/to/file3"

# End index of header in first file
file1_start=2138
midpoint=$(( $file1_start + 1 ))

file1_wc=($(wc $file1))
file2_wc=($(wc $file2))
file3_wc=($(wc $file3))

# Get a line count for the three different flat text files, as an upper bound index
ceil1=${file1_wc[0]}
ceil2=${file2_wc[0]}
ceil3=${file3_wc[0]}

# Initialize end point indices
line="$(head -$midpoint $file1 | tail -1 | awk '{print $1;}')"
line2=$(grep -n -e "$line" $file2 | cut -f1 -d:)
line3=$(grep -n -e "$line" $file3 | cut -f1 -d:)

# Initialize starting point indices
last1=$midpoint
last2=$line2
last3=$line3

# Update "midpoint" index
midpoint=$(($midpoint+$ceil1/$increment))

while [ $midpoint -lt $ceil1 ]
do

 line="$(head -$midpoint $file1 | tail -1 | awk '{print $1;}')"
 line2=$(grep -n -e "$line" $file2 | cut -f1 -d:)
 line3=$(grep -n -e "$line" $file3 | cut -f1 -d:)

 # Calculate range of indices for subset number $increment
 span1=$(($midpoint-$last1))

 echo "Line of interest: span2=$(($line2-$last2))"
 # ***NOTE***: The below statement is where it is failing for odd $increment
 span2=$(($line2-$last2))

 span3=$(($line3-$last3))

 # Set index variables for next iteration of file traversal
 index=$(($index+1))
 last1=$midpoint
 last2=$line2
 last3=$line3

 # Increment midpoint index variable
 midpoint=$(($midpoint+$ceil1/$increment))

done

非常感谢您的反馈,在此先感谢。


更新:通过添加“set -x”并查看调用堆栈,我确定表达式

 line2=$(grep -n -e "$line" $file2 | cut -f1 -d:)

greping 不止一行。因此,在我上面提供的示例中,$line2 等于“153026\n153027”,并且不是减法的合理参数,因此存在语法错误。解决此问题的一种方法是通过管道连接到头部,例如

 line2=$(grep -n -e "$line" $file2 | cut -f1 -d: | head -1)

只考虑 grep 产生的第一行。

【问题讨论】:

  • 您是否尝试过将set -x 放入脚本中以便观察其执行情况?这是调试 shell 脚本的常用方法。
  • 检查坏行中的非打印字符
  • 确保使用 bash 运行它:bash your_script.sh。你能展示你的bash版本吗? bash --version
  • dos2unix myScriptName?修复了 S.O. 上 1/2 的神秘问题。 :-) 。祝你好运。
  • 您可以回答自己的问题。我只是给你调试提示,我没有弄清楚解决方案。

标签: bash shell


【解决方案1】:

ncemami:通过添加“set -x”并查看调用堆栈,我确定表达式

 line2=$(grep -n -e "$line" $file2 | cut -f1 -d:)

greping 不止一行。因此,在我上面提供的示例中,$line2 等于“153026\n153027”,并且不是减法的合理参数,因此存在语法错误。解决此问题的一种方法是通过管道连接到头部,例如

 line2=$(grep -n -e "$line" $file2 | cut -f1 -d: | head -1)

只考虑 grep 产生的第一行。

【讨论】:

  • 谢谢!你的回答让我意识到我的一个价值观包含了一个额外的空间,不适合比较。
猜你喜欢
  • 1970-01-01
  • 2014-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多