编辑自己的Bash脚本

时间:2010-07-02 18:56:38

标签: bash

我正在尝试编写一个可以自行编辑的bash脚本。我试图使用的代码行是:

sed "s/$STRING_TO_REPLACE/$NEW_STRING/" < $0 > $0

但是在运行脚本后我最终得到一个空文件。有什么建议吗?

我正在创建一个包含两个包含默认值的变量的脚本。唯一的问题是,这些默认值对于将要使用它的许多站中的每一个都是不同的。我宁愿没有运行这些站的人不得不打开脚本并自己编辑默认值,所以我想包括更改脚本中默认值的功能。我的要求之一是脚本必须是自包含的;脚本中没有其他文件,并且没有环境变量。这将要求脚本能够自己编辑。

7 个答案:

答案 0 :(得分:2)

如果您想使用sed进行就地替换,请使用-i开关。

我不建议动态地重写当前正在执行的脚本。我不确定它是否可能,但如果是,那肯定会很有趣(阅读:难度)维护代码: - )

答案 1 :(得分:2)

您正在尝试读取和写入相同的流,这是一种糟糕的编程习惯,通常会导致错误。

这是你应该做的:

  1. 写入临时文件
  2. 删除原始文件
  3. 将temp重命名为原始文件名

    sed“s / $ STRING_TO_REPLACE / $ NEW_STRING /”&lt; $ 0&gt;温度

    rm $ 0

    mv temp $ 1

  4. 我还没有完成bash脚本,所以请确认我有正确的命令。

答案 2 :(得分:1)

首先,这是一个非常糟糕的主意,我无法想象它的任何用例都不能被不属于此的内容所覆盖。

发生这种情况的原因是因为当你执行&gt;文件时,它会以读取模式打开文件并将其截断为0长度,并且输入无需读取。您需要使用临时文件。您可以看到更多信息here

答案 3 :(得分:0)

编辑:正如上面DwB所述,将您的代码分成两个代码:一个核心脚本可以执行您想要的操作,另一个核心脚本可以修改,执行,并可能终止第一个。 这是你应该做的第一件事

另请注意,您应编辑正在运行的shell脚本。阅读问题my answerEdit shell script while it's running

答案 4 :(得分:0)

我正在做的事情,我也建议,有一个配置文件($ HOME / .myscript.cfg)并让你的脚本检测它的存在(和版本)并相应地创建/更新它。通过这种方式,第一次运行可以提出问题,后续运行可以完成工作,而不会给操作员带来重复性问题。

答案 5 :(得分:0)

  

但是在运行脚本后我最终得到一个空文件。有什么建议吗?


有点迟来的回复......一个可能的解决方案是,在脚本的退出命令之后,您的脚本可以包含可修改的设置

为了避免意外更改除了这些设置以外的任何内容,最好使用适当的前缀,如下所示:

@SETTINGS
@setting-homepage=http://www.goatse.cx
@setting-dns=4.4.2.2
下面是一个修改两个变量的示例:一个用于指定默认浏览器主页(默认值为:www.goatse.cx,new:www.google.com),另一个用于更改DNS(默认值:4.4.2.2,new: 8.8.8.8)。



警告词

sed用于修改包含所需设置的行号的内容。如果这里有错误,它将 spaz out并用sed相关的疯狂覆盖脚本中的每一行。一个解决方案可能是让脚本编写另一个脚本然后用于修改原始脚本。另一种方法可能是包含一个条件语句,它只在确认匹配存在后才执行sed替换。或者更简单地说,匹配所需的设置字符串而不仅仅是行号。

编辑:似乎尝试与sed执行字符串匹配会导致一些奇怪的脚本自噬。我认为您需要指定低于退出命令的行号。



#!/bin/bash

# find settings and extract their values
settingDefaultHomepage=$(grep ^@setting-homepage $0 |  sed 's/@setting-homepage=*//')
settingDefaultDNS=$(grep ^@setting-dns $0 |  sed 's/@setting-dns=*//')


echo "Default browser homepage = $settingDefaultHomepage"
echo "Default DNS = $settingDefaultDNS"


# find line number of setting, to be used when modifying the value
settingLineHomepage=$(awk '/^@setting-homepage/ {print FNR}' $0)
settingLineDNS=$(awk '/^@setting-dns/ {print FNR}' $0)

echo "Line of setting for browser homepage = $settingLineHomepage"
echo "Line of setting for DNS = $settingLineDNS"



# modify the settings using line number above
sed -i $settingLineHomepage's/.*/@setting-homepage=www.google.com/' $0
sed -i $settingLineDNS's/.*/@setting-dns=8.8.8.8/' $0



exit


@SETTINGS
@setting-homepage=www.goatse.cx
@setting-dns=4.4.2.2



答案 6 :(得分:-1)

Perl处理就地编辑。试试这个:

perl -npi -e "s/$STRING_TO_REPLACE/$NEW_STRING/g" < $0