来自命令的多行输出的 Bash for 循环

Kir*_*ema 2 bash for-loop mysqldump multiline

我必须为我们的数据库编写一个小的多线程 mysqldump 脚本,但由于单个表包含一个空格,我遇到了一些问题。

我的第一次尝试非常简单:

for TABLE in `mysql -u user -ppassword -e 'show tables;' dbname`  
do
    while [ 1 ]
    do
        if [ `jobs -r | wc -l` -lt $MAXTHREADS ]
        then
            break
        else
            sleep 1
        fi
    done

    mysqldump -u user -ppassword dbname $TABLE
done
Run Code Online (Sandbox Code Playgroud)

不幸的是,有一张桌子,里面有一个空格。我在 google 上搜索了一点,使用 for 循环和命令的多行输出,更改 $IFS 变量是一个常见的解决方案。所以我把它改成了\n\b(不知何故,当我只使用\n时$IFS是空的)但这是一个坏主意,因为它导致mysql命令不再起作用。

我认为,当我事先获取表并在每次在 for 循环中使用 mysqldump 时将 $IFS 改回时,这应该不是问题。但是我又弄错了,因为我现在只有一行所有表。
我目前的代码:

TABLES=$(mysql -u user -ppassword -e "show tables" dbname | tail -n +2)

OIFS="$IFS"
AIFS=$(echo -en "\n\b")
IFS="$AIFS"

for TABLE in "$TABLES"
do
    IFS="$OIFS"
    while [ 1 ]
    do
        if [ `jobs -r | wc -l` -lt $MAXTHREADS ]
        then
            break
        else
            sleep 1
        fi
    done

    mysqldump -u user -ppassword dbname $TABLE
    IFS="$AIFS"

done
IFS="$OIFS"
Run Code Online (Sandbox Code Playgroud)

当我尝试回显 $TABLES 变量时,我每行得到一个表,但 for 循环只运行一次,其中 $TABLE 变量包含所有表。

提前致谢
kiro

Gor*_*son 6

使用 while 循环代替 for:

mysql -u user -ppassword -e "show tables" dbname | tail -n +2 | while read TABLE
do
    ...
done
Run Code Online (Sandbox Code Playgroud)

...除非您需要在循环内设置任何变量并在循环退出后让它们可用。由于这使 while 循环成为管道的一部分,因此它在子 shell 中运行,并且变量等不会转移到主 shell。如果您需要在主 shell 中运行循环,您可以使用 bash 的进程替换功能而不是标准管道:

while read TABLE
do
    ...
done < <(mysql -u user -ppassword -e "show tables" dbname | tail -n +2)
Run Code Online (Sandbox Code Playgroud)