【问题标题】:Find and replace using a sh file使用 sh 文件查找和替换
【发布时间】:2011-10-22 01:10:07
【问题描述】:

我正在编写一个自动备份和镜像脚本,它将或多或少地复制文件、数据库、设置权限,并稍微修改镜像文件,以便它们在具有备份文件的另一台服务器上工作。除了重新配置之外,我已经编写并设置了其他所有内容。我所有的尝试都失败了,我不知道如何解决它。

所以这些是相关的行(为公众使用而修改):

FOLDER="kf.hammertime.com.au"
SERVER="fulcan"
BACKUPUSER="backupclient3"
DESTINATION="/var/www/Backup-Server"
SOURCE="/var/www"

RECONFIG="1"

if [ "${RECONFIG}" = "1" ]
then
#Original to be replace
echo Reconfiguring website for the mirrored site.
REPLACESTRING10="define (\'ROOT_PATH\', \'\/var\/www\/${FOLDER}\/trunk\')"
REPLACESTRING20="define ('DB_PASSWORD', 'hammertime1')"
REPLACESTRING30="define ('DB_USERNAME', 'hammertime2')"
REPLACESTRING40="define ('DB_HOST', 'localhost')"

#String to be replaced
REPLACESTRING11="define ('ROOT_PATH', '${SOURCE}\/${FOLDER}')"
REPLACESTRING21="define ('DB_PASSWORD', 'hammertime3')"
REPLACESTRING31="define ('DB_USERNAME', 'hammertime4')"
REPLACESTRING41="define ('DB_HOST', 'hammertime5')"

REPLACESTRING12="define (\'ROOT_PATH\', \'${SOURCE}\/${FOLDER}\/trunk\')"

echo ${REPLACESTRING10}

#Reconfigure various configuration files for Backup-Server active use

#find /your/home/dir -name "*.txt" | xargs perl -pi -e 's/stringtoreplace/replacementstring/g'

#Edits the files regardless if its in trunk or not. Will come up with errors.

#sudo replace "${REPLACESTRING10}" "${REPLACESTRING12}" <${DESTINATION}/${FOLDER}/trunk/lib/config.php> ${DESTINATION}/${FOLDER}/trunk/lib/config2.php

#sudo sed -i s/"${REPLACESTRING10}"/"${REPLACESTRING12}"/g  ${DESTINATION}/${FOLDER}/trunk/lib/config.php

#sudo perl -i -p -e 's{${REPLACESTRING10}}{${REPLACESTRING12}}g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php


sudo sed -i 's/${REPLACESTRING10}/${REPLACESTRING12}/g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php

#sudo sed -i 's/${REPLACESTRING10}/${REPLACESTRING11}/g' ${DESTINATION}/${FOLDER}/lib/config.php

#sudo sed -i 's/${REPLACESTRING20}/${REPLACESTRING21}/g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php
#sudo sed -i 's/${REPLACESTRING20}/${REPLACESTRING21}/g' ${DESTINATION}/${FOLDER}/lib/config.php

#sudo sed -i 's/${REPLACESTRING30}/${REPLACESTRING31}/g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php
#sudo sed -i 's/${REPLACESTRING30}/${REPLACESTRING31}/g' ${DESTINATION}/${FOLDER}/lib/config.php

#sudo sed -i 's/${REPLACESTRING40}/${REPLACESTRING41}/g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php
#sudo sed -i 's/${REPLACESTRING40}/${REPLACESTRING41}/g' ${DESTINATION}/${FOLDER}/lib/config.php
fi

所以简而言之,“sudo sed -i 's/${REPLACESTRING10}/${REPLACESTRING12}/g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php”这一行不需要在变量方面非常好。

所以我尝试使用 perl 替代方案,但无济于事(但我本可以使用它)。我的大部分尝试都列在那里。以及替换。

我只需要更改单个文件中的某些行(行号可以更改)。

提前感谢您的时间和耐心(顺便说一下,这是第一次编写 SH 脚本,我已经习惯了 BAT,所以我确定我已经完成了相当一部分,但它运行良好,没有错误)

编辑: 文件块如下所示:

define ('ROOT_PATH', '/var/www/kf.hammertime.com.au/trunk');
define ('DB_HOST', 'hammertime1');
define ('DB_USERNAME', 'hammertime2');
define ('DB_PASSWORD', 'localhost');

我想把它改成:

define ('ROOT_PATH', '/var/www/Backup-Server/kf.hammertime.com.au/trunk');
define ('DB_HOST', 'hammertime3');
define ('DB_USERNAME', 'hammertime4');
define ('DB_PASSWORD', 'hammertime5');

但其中一些已编辑的项目将是变量...

【问题讨论】:

    标签: bash replace sed find sh


    【解决方案1】:

    sed 字符串中的变量替换必须用双引号引起来。也就是说,你有

     sudo sed -i 's/${REPLACESTRING10}/${REPLACESTRING12}/g' ${DESTINATION}/${FOLDER}/trunk/lib/config.php
    

    替换为

     sudo sed -i "s/${REPLACESTRING10}/${REPLACESTRING12}/g" ${DESTINATION}/${FOLDER}/trunk/lib/config.php
    

    解决这个问题,然后告诉我们下一个问题是什么。您可能需要转义嵌入在 REPLACESTRINGn 中的任何空格或制表符字符,例如

    REPLACESTRING20="define\ ('DB_PASSWORD',\ 'hammertime1')"
    # ---------------------^  --------------^
    

    编辑

    当然,所有 sed 问题的杀手是搜索字符串或替换字符串中嵌入的“/”。大多数seds允许使用除'/'之外的其他字符,所以试试

     sudo sed -i "s#${REPLACESTRING10}#${REPLACESTRING12}#g" ${DESTINATION}/${FOLDER}/trunk/lib/config.php
    

    一些 seds '坚持'如果第一个字符不是'/',你就转义它,所以如果只是简单的s#...#...#g' doesn't work, trys\#...#...`(只是第一次提到#)。并且如果您的目标或 repl 字符串中有 '#' 字符,那么您必须找到不同的分隔符来使用。

    如果您使用 shell 调试模式会有所帮助,即set -vx(插入脚本顶部附近)。然后,您将看到每一行在执行时将变量扩展为分配的值。

    我希望这会有所帮助。

    附:由于您似乎是新用户,如果您得到对您有帮助的答案,请记住将其标记为已接受,和/或给它一个 +(或 -)作为有用的答案。

    【讨论】:

    • 好吧,当我尝试你的建议时,我明白了:------ sudo sed -i 's/define \'\''ROOT_PATH\'\''\, \'\ ''\/var\/www\/jb.qk.com.au\/trunk\'\''/define \'\''ROOT_PATH\'\'', \'\''/var/www\/ jb.qk.com.au\/trunk\'\''/g' /var/www/Backup-Server/jb.qk.com.au/trunk/lib/config.php sed: -e 表达式 #1, char 87: 's' 的未知选项-----我没有转义什么?
    • 最后一次编辑就是这样。非常感谢你 :)。如果我想不出来,我会扯掉我的头发.....
    【解决方案2】:
    sudo sed -i s+$REPLACESTRING10+$REPLACESTRING12+g ...
    

    【讨论】:

      【解决方案3】:

      单引号防止替换,你需要使用双引号。但更重要的是,您需要将源字符串更改为正则表达式,因为这是 sedperl(以及其他类似工具)所理解的。

      Perl 实际上可以为您将文字字符串更改为正则表达式,如下所示:

      perl -pi -e 'BEGIN { $src = quotemeta(shift @ARGV); }
          s/$src/'"${REPLACESTRING12}/g" "$REPLACESTRING10" file
      

      多个替换可能都应该由单个脚本完成,无论是sedperl 还是其他。 (显然,每个目标文件一个。)这也应该有助于使脚本更具可读性。

      此外,进行就地编辑似乎有点冒险。也许您应该有一个“源”文件,您可以根据需要进行修改并安装到不同的目的地?

      【讨论】:

      • 您打算对两个文件进行相同的更改吗?如果是这样,显然对这两个文件应用相同的替换脚本。从您的示例中很难判断最终结果应该是什么。
      猜你喜欢
      • 2018-10-19
      • 1970-01-01
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-01
      • 2011-06-12
      • 2012-02-14
      相关资源
      最近更新 更多