bash脚本中的错误:算术错误

时间:2018-08-25 12:22:40

标签: bash

我写了一个简单的脚本来从一堆文件(*.out)中提取文本,并在开头添加两行,在末尾添加一行。然后,我将提取的文本与另一个文件一起添加以创建一个新文件。脚本在这里。

#!/usr/bin/env bash
#A simple bash script to extract text from *.out and create another file 
for f in *.out; do
#In the following line, n is a number which is extracted from the file name
        n=$(echo $f | cut -d_ -f6)
        t=$((2 * $n ))
#To extract the necessary text/data
        grep "  B  " $f | tail -${t} | awk 'BEGIN {OFS=" ";} {print $1, $4, $5, $6}' | rev | column -t | rev > xyz.xyz
#To add some text as the first, second and last lines.
        sed -i '1i -1 2' xyz.xyz
        sed -i '1i $molecule' xyz.xyz
        echo '$end' >> xyz.xyz
#To combine the extracted info with another file (ea_input.in)
        cat xyz.xyz ./input_ea.in > "${f/abc.out/pqr.in}"
     done

./script.sh: line 4: (ls file*.out | cut -d_ -f6: syntax error: invalid arithmetic operator (error token is ".out) | cut -d_ -f6")

如何纠正此错误?

2 个答案:

答案 0 :(得分:1)

在bash中,当您使用时:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

sess = tf.Session()
order = 5
x = np.zeros(30)
x[10] = 1
y = tf.layers.conv1d(inputs=tf.reshape(x,[1, len(x), 1]),
                     filters=1,
                     kernel_size=order,
                     padding='same')
sess.run(tf.global_variables_initializer())
y_out = sess.run(y)

# get coef
coef = sess.run(tf.all_variables()[-2].value())
print(coef.reshape(order))

它将括号的内容视为算术表达式,返回计算结果,以及使用时:

$(( ... ))

执行括号中的内容并返回输出。

因此,要解决您的问题,只需将第4行替换为:

$( ... )

这将外部双括号替换为单个,并删除了n=$(ls $f | cut -d_ -f6) 周围多余的括号。

答案 1 :(得分:1)

可以通过在括号之间添加空格来避免算术错误。您已经在脚本的其他位置正确使用了var=$((arithmetic expression)),因此应该很容易理解为什么$( ((ls "$f") | cut -d_ -f6))需要空格。但是子外壳也是完全多余的。您想要$(ls "$f" | cut -d_ -f6)。除了ls在这里没有做任何有用的事情;使用$(echo "$f" | cut -d_ -f6)。除了外壳可以很容易地(尽管有点笨拙)之外,还可以提取带有参数替换的子字符串。 "${f#*_*_*_*_*_}"。除非您始终在脚本中使用Awk,否则在Awk中执行此操作(以及执行更多操作)更有意义。

这里是将大多数处理重构为Awk的尝试。

for f in *.out; do
     awk 'BEGIN {OFS=" " }
            # Extract 6th _-separated field from input filename
            FNR==1 { split(FILENAME, f, "_"); t=2*f[6] }
            # If input matches regex, add to array b
            /  B  / { b[++i] = $1 OFS $4 OFS $5 OFS $6 }
            # If array size reaches t, start overwriting old values
            i==t { i=0; m=t }
            END {
                # Print two prefix lines
                print "$molecule"; print -1, 2;
                # Handle array smaller than t
                if (!m) m=i
                # Print starting from oldest values (index i + 1) 
                for(j=1; j<=m; j++) {
                    # Wrap to beginning of array at end
                    if(i+j > t) i-=t
                    print b[i+j]; }
                print "$end" }' "$f" |
        rev | column -t | rev |
        cat -  ./input_ea.in > "${f/foo.out/bar.in}"
     done

还请注意我们如何避免使用临时文件(如果没有Awk重构,这当然也可以避免),以及我们如何注意用双引号引起来的所有文件名变量。

数组b包含(最多)来自匹配行的最新t值;我们将它们收集到一个数组中,当到达索引t时,通过将索引i包装回到数组的开头,将它们限制为永远不能包含超过t个值。这种“圆形数组”避免了在内存中保留太多的值,如果输入文件包含许多匹配项,这会使脚本变慢。