Linux 编写bash脚本以更改文本并写入日志

Linux 编写bash脚本以更改文本并写入日志,linux,bash,Linux,Bash,我已经编写了一个非常简单的bash脚本来帮助我从dev迁移到staging。它所做的是删除staging中的所有文件,将文件从dev复制到stage 但是,config.inc.php文件需要将“dev”的第一个实例更改为“stage”,而不需要更改其他实例 第二,每次我运行它(我从dev目录运行脚本),我都希望它在dev目录中写回一个日志,它将把我运行staging bash脚本的日期/时间戳附加到这个日志中 谢谢。使用流编辑器实用程序sed可以很好地完成第一部分(编辑文件): sed -i

我已经编写了一个非常简单的bash脚本来帮助我从dev迁移到staging。它所做的是删除staging中的所有文件,将文件从dev复制到stage

但是,config.inc.php文件需要将“dev”的第一个实例更改为“stage”,而不需要更改其他实例

第二,每次我运行它(我从dev目录运行脚本),我都希望它在dev目录中写回一个日志,它将把我运行staging bash脚本的日期/时间戳附加到这个日志中

谢谢。

使用流编辑器实用程序
sed可以很好地完成第一部分(编辑文件):

sed -i -e s/dev/stage/ config.inc.php

这将在不备份的情况下就地编辑文件(
-i
),使用表达式
/dev/stage/
-e
)将一个表达式替换为另一个表达式。

更改文件中的单词:

cat config.inc.php | sed 's:dev::stage' > config.inc.php.new 
要附加到日志文件,请执行以下操作:

echo $timestamp >> mylogfile.log

这只会将“dev”的第一个外观更改为“stage”

请注意,它将“devel”更改为“stageel”。这个版本的行为和你想要的一样,只搜索一个“dev”,而不是一个“devel”(事实上,
s/\/stage/
,因为替换表达式应该可以工作,但它似乎没有按预期工作?如果有更多sed-fu的人可以解释,我会很高兴。)


由Jonathan Leffler补充

  • 假设其他问题得到解决(见下文),第二个
    sed
    命令仍然可以将
    devel
    更改为
    stagel
    ,如果该行包含,例如,“将devel代码从/some/dev/location移动到/some/stage/location”
  • 另外,第二个
    sed
    命令将映射包含
    dev
    的第一行和第二行之间找到的每个
    dev
    。如果有多个匹配行,则这很重要,而原始的“
    0,/dev/
    ”(或修订的“
    0,/\/
    ”)仅根据请求匹配第一行
  • “s/\/stage/”
    不起作用的原因不是
    sed
    问题,而是shell问题。使用单引号,你几乎就可以了。使用双引号时,反斜杠小于序列显示为小于
  • 经验法则:在包含正则表达式材料的shell脚本中的任何参数周围使用单引号。除非正则表达式中满是单引号,否则将正则表达式中的每个单引号替换为序列引号、反斜杠、引号、引号“
    ”\'
    ”。(第一个引号终止单引号字符串;反斜杠引号是单引号;最后一个引号重新启动单引号字符串。)
  • 注意,“
    -i
    ”选项是对
    sed
    的GNU扩展;这是答案的合法部分,因为问题被标记为Linux,其中使用了GNU
    sed
    ;如果需要迁移到Solaris、AIX、HP-UX等平台,请注意
  • 最后,
    sed
    不支持扩展正则表达式作为标准;您必须使用“
    -r
    ”选项在GNU中显式启用它们
据我估计,如果需要覆盖,命令应该是:

sed -i -r '0,/\<dev\>/s/\<dev\>/stage/' config.inc.php
sed-i-r'0,/\/s/\/stage/'config.inc.php

这将dev的每个实例都更改为StageGratuations,您刚刚赢得了“无用的cat使用”奖,无意冒犯,振作起来:)同意“无用的cat”——尽管在某个地方,Unix创始人之一评论说,cat作为通用数据收集器有一些优点,并且是各种替代重定向机制的意外副作用。如果行中包含“将devel代码从/some/dev/location移动到/some/stage/location”,则第二个sed命令仍然可以将devel更改为stagel,第二个sed命令将在包含dev的第一行和第二行之间映射找到的每个dev,如果模式匹配相同,问题就不会那么严重了。至于“s/\/stage/”不起作用的原因,这不是sed问题,而是shell问题。使用单引号,你会更接近OK;使用双引号,反斜杠lessthan序列看起来就像sed的lessthan一样;您必须在GNU中使用-r选项显式地启用它们。谢谢大家,我将尝试这三个变量,并让大家都知道!注意:这只是将dev的第一个实例更改为stage,而不是任何其他后续实例……谢谢,我选择了Jonathan的——它更健壮,因此我可以根据需要进行更改和修改,也更清楚地说明了只有第一个实例。我主要使用第1行中的解决方案,因为我不清楚它们之间的区别,但我知道字符串的第一个实例是fa
sed -i  "/\<dev\>/,/\<dev\>/ s/dev/stage/" config.inc.php
date >> /path/to/dev/run.log
sed -i -r '0,/\<dev\>/s/\<dev\>/stage/' config.inc.php