Bash试图设置,创建和重用变量

时间:2018-02-01 23:05:07

标签: bash

感谢: @Diego Torres Milano

https://stackoverflow.com/a/48569466/175063

#!/bin/bash
find /home -type f -name "wp-config.php" -print0 | while read -rd $'\x00' f
do
    cat '[%s]\n' "$f" | grep DB_NAME | cut -d \' -f 4
done

但是,似乎缺少一些东西:

./test.sh: line 5: unexpected EOF while looking for matching ``'
./test.sh: line 8: syntax error: unexpected end of file

结果:

#!/bin/bash
find /home -type f -name "wp-config.php" -print0 | while read -rd $'\x00' f
do
    printf '%s\n' "$f"
    WPDBNAME=`cat '%s\n' "$f" | grep DB_NAME | cut -d \' -f 4
    WPDBUSER=`cat '%s\n' "$f" | grep DB_USER | cut -d \' -f 4
    WPDBPASS=`cat '%s\n' "$f" | grep DB_PASSWORD | cut -d \' -f 4
    echo $WPDBNAME
    echo $WPDBUSER
    echo $WPDBPASS
done

最终,我想要的是:

f 0 = 4
f 1 = 5
...

谢谢!

2 个答案:

答案 0 :(得分:2)

这里有很多问题;首先,我将第二个@Cyrus' shellcheck.net的推荐 - 它会发现一些常见错误,包括脚本中的几个错误。无论如何,我看到的问题是:

  • 您获得的错误是由于不平衡的反引号造成的。问题的原始版本有这一行:

    cat '[%s]\n' "$f" | grep DB_NAME | cut -d \' -f 4`
    

    并且该行末尾的单独反引导将导致错误,例如您正在获得的错误。编辑后的版本没有(并且因此不会给出报告的错误),但是"我想要的东西是"脚本有如下行:

    WPDBNAME=`cat '%s\n' "$f" | grep DB_NAME | cut -d \' -f 4
    

    =之后有一个无与伦比的反引号。我的建议是使用$( )而不是反引号 - 它们更容易阅读(因此更难搞乱),在功能上等同,并且没有反引号导致的微妙转义问题。所以,你应该使用类似的东西:

    WPDBNAME=$(cat '%s\n' "$f" | grep DB_PASSWORD | cut -d \' -f 4)
    
  • 除此之外仍然是错误的。 '%s\n'部分是printf格式字符串,在您复制的示例中需要,但在此处完全不相关。如果您将该参数提供给cat命令,它将尝试打开名为%s\n的文件并失败。把它关掉:

    WPDBNAME=$(cat "$f" | grep DB_PASSWORD | cut -d \' -f 4)
    
  • 下一个不是一个真正的问题,就像一般建议一样:只要你看到cat somefile | somethingcommandcat命令实际上并没有做任何有用的事情(它被称为&#34;无用的猫&#34;)。它可以替换为somecommand <somefile,或者,如果命令直接支持输入文件名,则somecommand somefilegrep支持输入文件名,因此您只需使用grep DB_PASSWORD "$f"

  • 实际上,grep something | cut something几乎总是可以使用awk进行简化。只需使用/pattern/搜索相关行,print搜索相关字段(使用-F定义字段分隔符):

    WPDBNAME=$(awk -F \' '/DB_NAME/ {print $4}' "$f")
    
  • 您没有遇到此问题,但使用全方位变量名称可能会造成麻烦,通常被视为不良做法。有许多变量对shell和/或其他程序有特殊意义,如果你不小心使用其中一个,它可能会产生坏/怪异的效果。经典案例是将PATH用于寻找可执行文件的地方列表之外的其他内容,然后使用suddenly getting "command not found" errors

    坚持使用小写或混合大小写变量,您不必担心这一点。

  • 打印结果时,不要对引号进行双引号。使用echo "$wpdbname"代替echo $wpdbname来防止因分词和全局扩展而导致的奇怪现象。

  • 但实际上,您根本不需要将各种参数捕获到变量中,您可以直接打印它们。也就是说,替换:

    wpdbname=$(awk -F \' '/DB_NAME/ {print $4}' "$f")
    echo "$wpdbname"
    

    使用:

    awk -F \' '/DB_NAME/ {print $4}' "$f"
    

最终剧本:

#!/bin/bash
find /home -type f -name "wp-config.php" -print0 | while read -rd $'\x00' f
do
    printf '%s\n' "$f"
    awk -F \' '/DB_NAME/ {print $4}' "$f"
    awk -F \' '/DB_USER/ {print $4}' "$f"
    awk -F \' '/DB_PASSWORD/ {print $4}' "$f"
done

注意:可以将单独的awk命令替换为搜索&amp;的单个XSLT命令。打印所有三个值。但是,按照它们在文件中出现的顺序打印它们,不一定是您期望的顺序。所以这可能更好。

答案 1 :(得分:0)

在响应者的指导下,我已经能够达成一个解决方案,现在正在运行的是一个cron工作。

#!/bin/bash
# delete files older than 7 days
find /home/dummyacount/sqlbackups/ -type f -name '*.gz' -mtime +7 -exec rm {} \;
# set a date variable
DT=$(date +"%m-%d-%Y")
find /home -type f -name "wp-config.php" -print0 | while read -rd $'\x00' f
do
        printf '%s\n' "$f"
        WPDBHOST=$(grep DB_HOST '%s\n' "$f" | cut -d \' -f 4)
        WPDBNAME=$(grep DB_NAME '%s\n' "$f" | cut -d \' -f 4)
        WPDBUSER=$(grep DB_USER '%s\n' "$f" | cut -d \' -f 4)
        WPDBPASS=$(grep DB_PASSWORD '%s\n' "$f" | cut -d \' -f 4)
        mysqldump -q -u "$WPDBUSER" -h "$WPDBHOST" -p "$WPDBPASS" "$WPDBNAME" | gzip -9 > "/home/dummyaccount/sqlbackups/$DT-$WPDBNAME.sql.gz"
done

我还必须回到:https://tomjn.com/2014/03/01/wordpress-bash-magic/

获取更多使用mysqldump整理的语法,但现在效果很好。