无法在 bash 脚本上运行 sed

无法在 bash 脚本上运行 sed

我正在研究一些无法正常工作的遗留代码,我发现其中一部分代码引发了问题。我希望有人能帮助我,告诉我这小部分脚本的具体功能是什么,以及什么可能导致它失败/无法执行。如果我在命令行上运行第一个 .sql 文件,一切都会顺利进行,而且我使用的 sql-logins 与脚本相同。

我有一个 update.sh 文件,它每晚运行一次,负责更新客户信息。但是当我们将客户添加到读取数据的文件中时,它无法生成新的数据库和存储过程实例。

代码片段:

#!/bin/bash

mysql_host="localhost"
mysql_id="root"
mysql_pwd="sudopwd"

read_dom () {
    local IFS=\>
    read -d \< ENTITY CONTENT
}

    .
    Some functioning code   
    .
    .
    Here is the part that does not work
        sed -i "s/tk[0-9]*;/tk$company_id;/1i" resources/sql/create_tk.sql
        mysql -h $mysql_host -u $mysql_id "-p$mysql_pwd" < resources/sql/create_tk.sql

        sed -i "s/tk[0-9]*/tk$company_id/gi" resources/sql/load_data_tk.sql
        mysql -h $mysql_host -u $mysql_id "-p$mysql_pwd"< resources/sql/load_data_tk.sql

    fi
done < info.xml

EN_MO=$(date +%s)
DIFF_MO=$[$EN_MO-$ST_MO] 
C_DATE=$(date +"%Y%m%d%H%M")

如果我理解正确的话 -我表示修改(更改脚本中正在使用的数据库)create_tk.sql。

/秒意味着它会对每个公司进行递归

/1i意味着保留字符串的 tk[0-9]*;/tk$company_id; 部分?并插入内容?

/gi与保留和模式空间有关吗?并插入内容?

如果有人能够澄清此代码片段的确切含义并指出导致无法实现其功能的原因,我将不胜感激。

谢谢大家的帮助。

答案1

我有一个 update.sh 文件,它每晚运行一次

我将其理解为“我通过 cron 启动它”。人们在使用 cron 时遇到的一个非常普遍的问题是他们对脚本运行的环境抱有期望。他们假设脚本将在他们的主目录中运行。

这正是你正在做的事情。所有sed命令都使用相对路径,因此当你在正确的目录中时它们会起作用...但cron在同一目录中吗?可能不是。

您可以在此处选择修复方法:

  1. 在所有脚本命令中使用绝对路径,例如/home/bob/dir/file
  2. 将脚本cd放入脚本顶部的正确目录(使用绝对路径)。
  3. 在操作之前将你的cron命令cd放入正确的目录中,例如:

    00 00 * * *   cd /home/bob && ./update.sh
    

关于权限的评论,如果您没有写权限来执行就地操作sed,您可以直接输出到您有写权限的地方,例如:

sed "s/tk[0-9]*;/tk$company_id;/1i" resources/sql/create_tk.sql > $HOME/temp.sql
mysql -h $mysql_host -u $mysql_id "-p$mysql_pwd" < $HOME/temp.sql
rm $HOME/temp.sql#

或者你实际上可以直接从管道sed进入mysql

sed "s/tk[0-9]*;/tk$company_id;/1i" resources/sql/create_tk.sql \
| mysql -h $mysql_host -u $mysql_id "-p$mysql_pwd"

这些方法不会改变原始resources/sql/*.sql文件,所以如果您需要编辑这些文件,您需要修复您的权限问题(无论它们是什么;用来stat filename查看发生了什么)

答案2

@Oli 告诉您为什么它可能失败,所以我只解释sed代码:

sed -i "s/tk[0-9]*;/tk$company_id;/1i"

s/PATTERN/REPLACEMENT/FLAGS替换运算符。它将替换PATTERNREPLACEMENTFLAGS(例如,gs///g)可以修改其行为。在这里,标志是N1在您的示例中),这意味着“仅替换 PATTERN 的第 N 个匹配项(这很奇怪,标志N通常用于替换N大于 1 的第 N 个匹配项。我不明白为什么这里需要它,sed默认情况下只会替换第一个匹配项)。i这使得匹配不区分大小写。

您的第二个sed有标志gii不区分大小写的匹配和g使替换全局化,它将应用于全部匹配当前行。如果没有它,则只有第一行会被替换,这就是为什么我看不出1上一个示例中该标志的意义所在。

答案3

您对 sed 选项的含义理解得并不完全正确。让我先解释一下它们,然后我们才能理解您的代码在做什么。

  • 选项-我意思是:不显示结果sed在终端上处理,写入文件。
  • 秒/语法是s/正则表达式/替换/。这意味着 sed 将替换匹配的字符串正则表达式正则表达式)的内容替代品

最后一个/是修饰符,它们影响 sed 如何处理这些行:

  • /G意思是“将替换应用到正则表达式的所有匹配项,而不仅仅是第一个。”
  • /1意思是“仅替换正则表达式的第一个匹配项。”
  • /我不区分大小写

/gi/1i是这些的组合。

因此,在您的代码中,这一行:

sed -i "s/tk[0-9]*;/tk$company_id;/gi" resources/sql/create_tk.sql

翻译如下(读作一个句子):

  • 在里面资源/sql/create_tk.sql文件 (-我选项)
  • 代替 (秒/
  • 所有字符串(/G
  • 从...开始传统知识(大写或小写字符/我),最后跟一个数字,然后跟一个分号
  • 通过字符串传统知识后面跟着变量的内容$company_id后面跟着一个分号

来源 :https://www.gnu.org/software/sed/manual/html_node/The-_0022s_0022-Command.html以及 sed 的手册页。

相关内容