【问题标题】:Why is this script creating a duplicate file and adding `-e` to the end?为什么这个脚本会创建一个重复文件并在末尾添加 `-e`?
【发布时间】:2016-12-04 09:54:29
【问题描述】:

我首先要说我不确定这是应该在这里还是超级用户,所以让我知道是否需要删除。

我正在 ~./bash_profile 中创建一个函数,以便在我启动新的 Laravel 项目时为我提供帮助。这是脚本:

function bootlaravel {
PROJECT=$1
echo "Magically creating a new Laravel project: $PROJECT..."
cd /Applications/MAMP/htdocs
laravel new $PROJECT
cd $PROJECT
git init
git add .
git commit -m "Install Laravel"
sed -i -e "s/DB_DATABASE=homestead/DB_DATABASE=$PROJECT/g" .env
sed -i -e "s/DB_USERNAME=homestead/DB_USERNAME=root/g" .env
sed -i -e "s/DB_PASSWORD=secret/DB_PASSWORD=/g" .env
/Applications/MAMP/Library/bin/mysql --host=localhost -uroot -proot -e "create database $PROJECT DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci"
open "http://$PROJECT.dev"
pstorm .
echo "Project: $PROJECT has been created. Have fun!"
}

用法类似于bootlaravel LaravelProjectName

sed 命令用于修改.env 文件,它实际上是创建一个.env-e 文件作为现有.env 文件的同级文件。我实际上无法理解它为什么这样做。不过,它会根据需要更改单词。

感谢任何帮助

【问题讨论】:

  • 这是在黑暗中拍摄的,但尝试sed -ie 而不是sed -i -e?由于-i 修改了扩展并且-e 被添加,我怀疑这就是问题所在。
  • @CormacO'Brien 差不多了,现在是.envehaha
  • 您想要备份吗?这就是sed -i 的想法,并且标志需要非零长度的扩展。如果没有,只需删除-i 标志,否则给它一个扩展名,如.bak
  • @CormacO'Brien 如果我放弃 -i 它不会进行替换
  • 如果您离开-i 选项,您必须提供一个输出文件。 -i 表示应该就地编辑文件,这需要备份。 @Kusalananda 的回答似乎是要走的路。

标签: bash sed terminal .bash-profile


【解决方案1】:

我通常建议不要使用sed -i,尤其是在尝试尝试或在平台之间移动脚本时。 BSD sed(例如在 OS X 上)需要-i 的参数,这可能也是您在文件中获得-e 后缀的原因(并且肯定 为什么-ie 给你一个e 后缀,即使使用GNU sed)。

您对sed 的三个调用可能会合并:

sed -e 's/DB_DATABASE=homestead/DB_DATABASE='"$PROJECT"'/g' \
    -e 's/DB_USERNAME=homestead/DB_USERNAME=root/g' \
    -e 's/DB_PASSWORD=secret/DB_PASSWORD=/g' .env >.env-new &&
mv -f .env-new .env

在我看来,使用临时文件为可移植性和健壮性付出了很小的代价。

另外,引用所有用户提供的字符串。在你的情况下,$PROJECT$1,你有一个很好的 SQL 注入可能性,否则,例如。

如果我的 SQL 引用正确,这将是修改后的 shell 函数:

function bootlaravel {
    local project="$1"

    echo "Magically creating a new Laravel project: $project..."

    cd /Applications/MAMP/htdocs || return 1    
    laravel new "$project"
    cd "$project" || return 1

    git init
    git add .
    git commit -m "Install Laravel"

    sed -e 's/DB_DATABASE=homestead/DB_DATABASE='"$project"'/g' \
        -e 's/DB_USERNAME=homestead/DB_USERNAME=root/g' \
        -e 's/DB_PASSWORD=secret/DB_PASSWORD=/g' .env >.env-new &&
    mv -f .env-new .env

    /Applications/MAMP/Library/bin/mysql \
        --host=localhost -uroot -proot <<SQL_END
CREATE DATABASE \`$project\`
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci
SQL_END

    open "http://$project.dev"
    pstorm .

    echo "Project: $project has been created. Have fun!"
}

这也使用小写的$project(大写通常用于环境变量),如果cd 中的任何一个失败,将返回非零状态。我还将project 声明为函数中的局部变量,以免新的shell 变量污染调用shell。空行等主要是为了便于阅读。

【讨论】:

  • 为避免任何意外,请始终将脚本用单引号括起来,而不是双引号,并在必要时断开,例如's/DB_DATABASE=homestead/DB_DATABASE='"$PROJECT"'/g' 并始终在 cmd file &gt; tmpmv tmp file 之间使用 &amp;&amp;,这样您就不会在失败时破坏原始文件。
  • @EdMorton 天哪!对不起!感谢您发现这一点。
  • @CharlesDuffy 我感谢您的意见。这似乎是 bash(来自 .bash_profile 的提及),因此将 project 声明为本地肯定是合适的。
  • @CharlesDuffy 不过我通常使用typeset,因为我最喜欢的shell ksh93 不理解local
  • 谢谢——我会尽量养成在编写跨 bash 和 ksh 工作的代码时喜欢它的习惯。
猜你喜欢
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多