我正在尝试编写一个可以自行编辑的bash脚本。我试图使用的代码行是:
sed "s/$STRING_TO_REPLACE/$NEW_STRING/" < $0 > $0
但是在运行脚本后我最终得到一个空文件。有什么建议吗?
我正在创建一个包含两个包含默认值的变量的脚本。唯一的问题是,这些默认值对于将要使用它的许多站中的每一个都是不同的。我宁愿没有运行这些站的人不得不打开脚本并自己编辑默认值,所以我想包括更改脚本中默认值的功能。我的要求之一是脚本必须是自包含的;脚本中没有其他文件,并且没有环境变量。这将要求脚本能够自己编辑。
答案 0 :(得分:2)
如果您想使用sed进行就地替换,请使用-i
开关。
我不建议动态地重写当前正在执行的脚本。我不确定它是否可能,但如果是,那肯定会很有趣(阅读:难度)维护代码: - )
答案 1 :(得分:2)
您正在尝试读取和写入相同的流,这是一种糟糕的编程习惯,通常会导致错误。
这是你应该做的:
将temp重命名为原始文件名
sed“s / $ STRING_TO_REPLACE / $ NEW_STRING /”&lt; $ 0&gt;温度
rm $ 0
mv temp $ 1
我还没有完成bash脚本,所以请确认我有正确的命令。
答案 2 :(得分:1)
首先,这是一个非常糟糕的主意,我无法想象它的任何用例都不能被不属于此的内容所覆盖。
发生这种情况的原因是因为当你执行&gt;文件时,它会以读取模式打开文件并将其截断为0长度,并且输入无需读取。您需要使用临时文件。您可以看到更多信息here。
答案 3 :(得分:0)
编辑:正如上面DwB所述,将您的代码分成两个代码:一个核心脚本可以执行您想要的操作,另一个核心脚本可以修改,执行,并可能终止第一个。 这是你应该做的第一件事。
另请注意,您应不编辑正在运行的shell脚本。阅读问题my answer的Edit 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