我有一个域数组,我试图迭代它并检查文件中的字符串是否与数组中的任何域匹配。但是,当 for 循环开始时,出现错误
line 64: www.google.com: syntax error: invalid arithmetic operator (error token is ".google.com")
数组和 for 循环如下所示:
sites=("www.google.com" "www.bing.com" "www.yahoo.com" "www.duckduckgo.com")
while read line; do
csvString=$(echo "$line");
greppedDomain=$(echo "$line" | grep -Eo '[A-Za-z0-9]{2,62}\.[A-Za-z0-9]{2,62}\.[A-Za-z]{2,62}');
for i in "${sites[@]}"; do
if [ "$greppedDomain" = "${sites[$i]}" ]
then
sitesOut+=($csvString);
fi
done
done < sitelist.txt
我目前不知所措,也许这是 grep 输出存储在变量中的方式的问题?
答案1
您使用数组的字符串元素作为数字索引:
for i in "${sites[@]}"; do
if [ "$greppedDomain" = "${sites[$i]}" ]
在数字索引数组中,当取消引用时,方括号中的索引部分实际上是一个算术表达式。这允许您进行索引算术,例如x[i]=${x[i+1]}
。
要重现该错误:
$ x=(a b c)
$ i="www.google.com"
$ echo "${x[i]}"
bash: www.google.com: syntax error: invalid arithmetic operator (error token is ".google.com")
为了演示数组索引的算术性质,让我们看一下算术表达式中的字符串:
$ echo $((www.google.com))
bash: www.google.com: syntax error: invalid arithmetic operator (error token is ".google.com")
同样的错误。
错误标记是“.google.com”——这是为什么?
解析
$((www.google.com))
该www
部分时将被视为外壳变量。- 在算术表达式中,变量不需要以美元符号作为前缀
- 测试:
a=5; b=7; echo $(( a * b ))
但是,从算术上讲,没有
.
运算符,因此解析器不知道如何处理表达式的其余部分。
答案2
在 bash 中迭代数组有两种标准方法。一种选择是直接循环元素值。这将运行设置为“www.google.com”的循环elem
,然后设置为“www.bing.com”等:
sites=("www.google.com" "www.bing.com" "www.yahoo.com" "www.duckduckgo.com")
for elem in "${sites[@]}"; do
echo "The element is: $elem"
done
另一种选择是循环数组索引,即 0、1、2 等(其中${sites[0]}
是“www.google.com”,${sites[1]}
是“www.bing.com”等):
for i in "${!sites[@]}"; do # The ! makes it list indexes, rather than elements
echo "The $i'th element is: ${sites[i]}"
done
这里的问题是您混合了这些方法,循环遍历元素值,然后将它们视为索引。
其他一些问题:
csvString=($echo "$line");
首先, 应该($
是$(
,其次你不应该使用$(echo ...)
- theecho
和 the$( )
大部分相互抵消(除了一些你可能不想要的可能的解析奇怪的情况)。只需使用这个:
csvString=$line
顺便说一句,注意到我没有在末尾加分号吗?在 shell 中,您不需要在 shell 的行末尾使用分号(除了一些奇怪的情况,例如结束case
选项的双分号)。仅当您将多个类似命令的内容放在同一行时才需要它们。例如,这个:
if somethingorother; then
echo "this"; echo "that"
fi
可以等价地写成:
if somethingorother
then
echo "this"
echo "that"
fi