aul*_*ron 12 shell scripting bash
我正在编写一个 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
Run Code Online (Sandbox Code Playgroud)
所以我尝试执行以下操作:
第一:创建一个脚本,self-update.sh我们称之为:
#!/bin/bash
fname=$(mktemp)
cat $0 | sed 's/BEFORE\./AFTER!./' > $fname
cp $fname $0
rm -f $fname
echo 'String: BEFORE.';
Run Code Online (Sandbox Code Playgroud)
脚本所做的是读取其代码,将单词“BEFORE”更改为“AFTER”,然后使用新代码重新编写自己。
2运行它:
chmod +x self-update.sh
./self-update.sh
Run Code Online (Sandbox Code Playgroud)
第三个奇迹...
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
Run Code Online (Sandbox Code Playgroud)
现在,我不会猜到在同一次调用中它会输出AFTER!,肯定会在第二次运行,但不会在第一次运行。
所以我的问题是:这是有意的(按设计)吗?还是因为 bash 运行脚本的方式?逐行或逐个命令。这种行为有什么用处吗?有什么例子吗?
编辑:我尝试重新格式化文件以将所有命令放在一行中,现在不起作用:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;echo 'String: BEFORE.';
Run Code Online (Sandbox Code Playgroud)
输出:
aularon@aularon-laptop:~$ ./self-update.sh #First invocation
String: BEFORE.
aularon@aularon-laptop:~$ ./self-update.sh #Second invocation
String: AFTER!.
Run Code Online (Sandbox Code Playgroud)
当将echo字符串移动到下一行时,将其与重写 ( cp) 调用分开:
#!/bin/bash
fname=$(mktemp);cat $0 | sed 's/BEFORE\./AFTER!./' > $fname;cp $fname $0;rm -f $fname;
echo 'String: BEFORE.';
Run Code Online (Sandbox Code Playgroud)
现在它又可以工作了:
aularon@aularon-laptop:~$ ./self-update.sh
String: AFTER!.
Run Code Online (Sandbox Code Playgroud)
phe*_*mer 15
这是设计使然。Bash 分块读取脚本。所以它会读取脚本的一部分,运行它可以运行的任何行,然后读取下一个块。
所以你遇到了这样的事情:
这变得更成问题的地方在于,如果您在字节 256 之前编辑任何内容。假设您删除了几行。然后脚本中位于字节 256 的数据现在位于其他位置,比如字节 156(早 100 个字节)。因此,当 bash 继续阅读时,它将获得最初的 356。
这只是一个例子。Bash 不一定一次读取 256 个字节。我不知道它一次读取多少,但没关系,行为仍然相同。