首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >/dev/stdin with herestring

/dev/stdin with herestring
EN

Stack Overflow用户
提问于 2013-03-11 10:46:21
回答 4查看 10.3K关注 0票数 7

我想要一个可以从文件或标准输入中获取输入的Bash脚本,例如,非常像grep

代码语言:javascript
复制
$ cat hw.txt
Hello world

$ grep wor hw.txt
Hello world

$ echo 'Hello world' | grep wor
Hello world

$ grep wor <<< 'Hello world'
Hello world

所有这些都运行得很漂亮。但是,使用以下脚本

代码语言:javascript
复制
read b < "${1-/dev/stdin}"
echo $b

如果使用using字符串,它将失败。

代码语言:javascript
复制
$ hw.sh hw.txt
Hello world

$ echo 'Hello world' | hw.sh
Hello world

$ hw.sh <<< 'Hello world'
/opt/a/hw.sh: line 1: /dev/stdin: No such file or directory
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-03-11 11:36:00

以这种方式使用/dev/stdin可能会有问题,因为您正在尝试使用文件系统(/dev/stdin)中的名称来获取标准输入的句柄,而不是使用bash已经提供给您的标准输入(文件描述符0)。

下面是一个小脚本,供您测试:

代码语言:javascript
复制
#!/bin/bash

echo "INFO: Listing of /dev"
ls -al /dev/stdin

echo "INFO: Listing of /proc/self/fd"
ls -al /proc/self/fd

echo "INFO: Contents of /tmp/sh-thd*"
cat /tmp/sh-thd*

read b < "${1-/dev/stdin}"
echo "b: $b"

在我的cygwin安装中,这会产生以下结果:

代码语言:javascript
复制
./s <<< 'Hello world'


$ ./s <<< 'Hello world'
INFO: Listing of /dev
lrwxrwxrwx 1 austin None 15 Jan 23  2012 /dev/stdin -> /proc/self/fd/0
INFO: Listing of /proc/self/fd
total 0
dr-xr-xr-x 2 austin None 0 Mar 11 14:27 .
dr-xr-xr-x 3 austin None 0 Mar 11 14:27 ..
lrwxrwxrwx 1 austin None 0 Mar 11 14:27 0 -> /tmp/sh-thd-1362969584
lrwxrwxrwx 1 austin None 0 Mar 11 14:27 1 -> /dev/tty0
lrwxrwxrwx 1 austin None 0 Mar 11 14:27 2 -> /dev/tty0
lrwxrwxrwx 1 austin None 0 Mar 11 14:27 3 -> /proc/5736/fd
INFO: Contents of /tmp/sh-thd*
cat: /tmp/sh-thd*: No such file or directory
./s: line 12: /dev/stdin: No such file or directory
b: 

这个输出显示的是,bash正在创建一个临时文件来保存您的HERE文档(/tmp/sh-thd-1362969584),并使其在文件描述符0、stdin上可用。但是,临时文件已从文件系统取消链接,因此无法通过文件系统名称(如/dev/stdin )通过引用进行访问。您可以通过读取文件描述符0来获取内容,但不能通过尝试打开/dev/stdin来获取。

在Linux上,上面的./s脚本给出了以下信息,表明该文件已解除链接:

代码语言:javascript
复制
INFO: Listing of /dev
lrwxrwxrwx 1 root root 15 Mar 11 09:26 /dev/stdin -> /proc/self/fd/0
INFO: Listing of /proc/self/fd
total 0
dr-x------ 2 austin austin  0 Mar 11 14:30 .
dr-xr-xr-x 7 austin austin  0 Mar 11 14:30 ..
lr-x------ 1 austin austin 64 Mar 11 14:30 0 -> /tmp/sh-thd-1362965400 (deleted) <---- /dev/stdin not found
lrwx------ 1 austin austin 64 Mar 11 14:30 1 -> /dev/pts/12
lrwx------ 1 austin austin 64 Mar 11 14:30 2 -> /dev/pts/12
lr-x------ 1 austin austin 64 Mar 11 14:30 3 -> /proc/10659/fd
INFO: Contents of /tmp/sh-thd*
cat: /tmp/sh-thd*: No such file or directory
b: Hello world

更改您的脚本以使用提供的标准输入,而不是尝试通过/dev/stdin引用。

代码语言:javascript
复制
if [ -n "$1" ]; then
    read b < "$1"
else
    read b
fi
票数 10
EN

Stack Overflow用户

发布于 2013-03-11 20:41:51

bash会专门解析某些文件名(如/dev/stdin),以便即使它们实际上不存在于文件系统中,也可以识别它们。如果您的脚本顶部没有#!/bin/bash,并且/dev/stdin不在您的文件系统中,那么您的脚本可以使用/bin/sh运行,这将使/dev/stdin实际上是一个文件。

(也许,这不应该是一个答案,而应该是对Austin's answer的评论。)

票数 1
EN

Stack Overflow用户

发布于 2013-03-11 11:25:23

代码语言:javascript
复制
$ cat ts.sh 
read b < "${1-/dev/stdin}"
echo $b

$ ./ts.sh <<< 'hello world'
hello world

对我来说没问题。我在Mac上使用bash 4.2.42。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15330402

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档