我正在编写bash脚本,并且在脚本等待while
循环中的某些输入时碰巧更新了代码(将脚本文件保存到磁盘)。回到终端并继续执行脚本的先前操作后,bash给出了有关文件语法的错误:
/home/aularon/bin/script: line 58: unexpected EOF while looking for matching `"'
/home/aularon/bin/script: line 67: syntax error: unexpected end of file
因此,我尝试执行以下操作:
第一个:创建脚本,self-update.sh
我们称它为:
#!/bin/bash
fname=$(mktemp)
cat $0 | sed 's/BEFORE\./AFTER!./' > $fname
cp $fname $0
rm -f $fname
echo 'String: BEFORE.';
脚本所做的是读取其代码,将单词“之前”更改为“之后”,然后使用新代码重新编写自身。
第二次运行:
chmod +x self-update.sh
./self-update.sh
第三奇迹
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
现在,我不会猜到在相同的调用之后它将输出!,当然可以在第二次运行中进行,但不能在第一次运行中进行。
所以我的问题是:(故意)是故意的吗?还是因为bash运行脚本的方式?逐行或逐条命令。有没有很好的利用这种行为?有什么例子吗?
编辑:我试图重新格式化文件以将所有命令放在一行中,它现在不起作用:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;echo 'String: BEFORE.';
输出:
aularon@aularon-laptop:~$ ./self-update.sh #First invocation
String: BEFORE.
aularon@aularon-laptop:~$ ./self-update.sh #Second invocation
String: AFTER!.
在将echo
字符串移至下一行时,将其与rewrite(cp
)调用分开:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;
echo 'String: BEFORE.';
现在它又可以工作了:
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
1
相关:stackoverflow.com/questions/4754592/...
—
马丁·冯·Wittich
我已经仔细阅读了源代码,但是对此并没有任何解释。我非常确定,尽管我已经看到一些自解压安装程序,这些安装程序几年前已作为shell脚本实现。这些脚本包含几行可执行的Shell命令,然后是这些命令读取的巨大数据块。因此,我假设这样做是为了使bash不必将整个脚本读入内存,而这对于大型的自解压脚本是不起作用的。
—
Martin von Wittich 2014年
下面是一个自解压脚本的例子:ftp.games.skynet.be/pub/wolfenstein/...
—
马丁·冯·Wittich
真好!我记得看到这些自安装脚本,AMD Catalyst驱动程序(专有)仍然像这样发货,它会自解压然后安装。这些取决于这种读取块中文件的行为。谢谢你的例子!
—
aularon 2014年