首页 > 解决方案 > sh 文件中的语法错误,但命令在 bash 上工作

问题描述

我是 bash 的新手,所以它一定是一件小事(我希望),但找不到问题的根源。

我有一个名为“url”的mysql数据库表,里面有很多url。我想要的是获取所有列表并使用 wget 访问它们。而已。

我有这个命令,并直接在 bash 中启动:

while read dbname; do dbarray+=("$dbname"); done < <(mysql -u MYUSER -pMYPASSWD, -e 'select url from mydb.url where borrado="n" and status=200 and id_idioma = 1 order by id_url asc' -B -N -s --skip-column-names) && for dbname in `echo ${dbarray[*]}`; do wget --no-check-certificate $dbname -O /dev/null > /dev/null 2>&1; done && unset dbarray

但是如果我把它放到一个 sh 文件中并执行它会抛出一个错误(请注意第 3 行是命令):

line 3: Syntax error near unexpected token `<'

我试图避免将 <() 管道方法用于“传统”管道,但同样,它可以直接在 bash 中作为命令执行,但不能在 .sh 文件中执行

 mysql -u MYUSER -pMYPASSWD -e 'select url from mydb.url where borrado="n" and status=200 and id_idioma = 1 order by id_url asc' -B -N -s --skip-column-names | while read dbname; do dbarray+=("$dbname"); done && for dbname in `echo ${dbarray[*]}`; do wget --no-check-certificate $dbname -O /dev/null > /dev/null 2>&1; done && unset dbarray

在这种情况下不会抛出错误,但它需要 1 秒才能完成并且什么都不做,不访问任何链接..

尝试执行./myfile.shsh myfile.sh,没有运气..

你能帮我让它从一个 sh 文件中工作,或者让我明白问题出在哪里吗?

请注意,它有 3 个与 && 连接的命令:1 获取所有 url 并用它们创建一个 var,2 循环 var 和 wget 每次迭代,3 删除 var。我认为是正确的方法,但也许我错了。明明要等完1做2,等完2做3,是我想要的。在您看来,这是正确的近似值吗?

干杯

标签: bashsyntax-errorsh

解决方案


在管道中,变量被设置在一个子shell中。换句话说:

echo foo | while read a; do var="$a"; done
echo "$var"

将打印一个空行,因为var当子外壳退出时消失。解决这个问题的一种方法是:

echo foo | { 
    while read a; do var="$a"; done
    echo "$var"
}

或者:

while read a; do var="$a"; done << EOF
$(echo foo)
EOF
echo "$var"

换句话说,您可以尝试:

mysql ... \
| { 
       while read dbname; do dbarray+=("$dbname"); done
       for dbname in "${dbarray[@]}"; do 
           wget ... "$dbname" ...
       done; 
}

不再需要取消设置dbarray,因为它会在块的末尾自动消失。它比使用更好,"${dbarray[@]}"而且您当然希望在调用中使用$(echo ${dbarray[*]}) 双引号。"$dbname"wget

请注意,这个数组似乎没有必要。只需直接wgetwhile/read循环中执行,而不是分配给数组。


推荐阅读