为什么这种“读取时”在终端中起作用,而在Shell脚本中却不起作用?


8

我在用信息文本填充WM栏时遇到了一个有趣的问题,该信息文本是通过设置根窗口的标题来应用的,即 xsetroot -name "clever words"

为此,在终端机上打印一笔财富可以正常工作:

fortune -s | while read -r; do xsetroot -name "$REPLY"; done

但是,从shell脚本运行时,同样会失败:

#!/bin/sh
cat /tmp/afile | while read; do echo "$REPLY"; done

产生:

$ sh afilereader
afilereader:2:读取:arg计数

当然,可以通过将我们的财富结果分配给一个变量,然后将xsetroot与所述变量一起使用来补救。但是我仍然想了解为什么这在脚本中不起作用。

我意识到管道两侧的每个命令都在其自己的子外壳中运行,但是看不到它们的局部变量如何影响while读取循环。还是变量甚至在循环迭代之间都超出范围?

我想念什么?

更新:sh我以前被链接到仪表板,这是正在取得POSIX兼容的过程。使用比较古老的bash解决了这个问题。


1
此处的破折号行为并不表明没有违反POSIX合规性。POSIX要求read不带变量就不能调用:pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html
dubiousjim 2012年

Answers:


10

您似乎正在运行中的第一个示例bash,而所指向的则是第二个示例/bin/sh,这是POSIX shell,要求传递参数以指定要输入的变量。将shebang更改为#!/bin/bash应该可以解决此问题。


好观察@克里斯!那个有效。我想我会阅读一下sh和之间的区别bash
反转

确实异常!我可以重新链接/bin/sh到bash,但想从现在起我就直接使用bash以避免歧义。谢谢:)
反转2012年

交互式shell通常在输出缓冲方面与shell脚本不同。如果在非交互式运行时生成命令的输出缓冲了其写入操作,则从进程间管道进行读取会导致各种奇怪的计时行为。
JesseM '17

5

在sh语法中,您需要

IFS= read -r REPLY

某些shell(如ksh,bash和zsh)允许read在不使用变量名的情况下被调用,但是它们之间的行为有所不同。例如查看

printf 'te\ st\\\na ' | "$shell" -c 'read; printf "%s\n" "<$REPLY>"'

在bash,zsh,pdksh和ksh93上都不同


这就是为什么我使用的shell不知道变量名的原因,这要感谢@Stephane。
反转
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.