首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在bash中倒带文件描述符,而不使用第二个文件描述符从bash中读取?

如何在bash中倒带文件描述符,而不使用第二个文件描述符从bash中读取?
EN

Unix & Linux用户
提问于 2022-02-21 07:25:02
回答 3查看 664关注 0票数 3

环境: GNU,版本3.2.57(1)-release (x86_64-apple-darwin20 20)

Try 0:

代码语言:javascript
复制
exec 3<> "$(mktemp)"    # open file descriptor 3 to a temp file for read/write
echo 'foo' >&3          # write 'foo' to descriptor 3
read bar <&3            # read contents of descriptor 3 to variable named bar (not using -u 3)
echo $?                 # exit status returns "1"
exec 3>&-               # close file descriptor 3

在上面的片段中,我希望$bar设置为"foo",但是它不能工作,因为文件描述符3中的位置位于文件描述符文件的末尾。

Try 1:

代码语言:javascript
复制
exec 3<> "$(mktemp)"    # open file descriptor 3 to a temp file for read/write
echo 'foo' >&3          # write 'foo' to descriptor 3
cat <&3                 # echo contents of of descriptor 3 to STDOUT
echo $?                 # exit status returns "0"
exec 3>&-               # close file descriptor 3

这也失败了,因为描述符3中的文件位置在末尾。

在C/C++中,您可以通过倒带(.)和搜寻(.)mktemp创建的文件临时文件的文件指针重置为文件的开头。

Known解决方法: 这里: (使用第二个描述符)

代码语言:javascript
复制
myTempFile="$(mktemp)"  # create temp file and assign to $myTempFile
exec 3> "$myTempFile"   # open file descriptor 3 for writing to $myTempFile
exec 4< "$myTempFile"   # open file descriptor 4 for reading of $myTempFile
echo 'foo' >&3          # write 'foo' to descriptor 3
read bar <&4            # read contents of descriptor 4 to variable named bar
echo $?                 # exit status returns "0"
echo "$bar"             # echo "foo"
exec 3>&-               # close file descriptor 3
exec 4>&-               # close file descriptor 4

The问题™(最后):

如何在bash中倒带文件描述符而不使用第二个文件描述符从一开始读取?

注意:我不想安装ksh93来使用它的倒带功能。

代码语言:javascript
复制
exec 3<> "$(mktemp)"
echo 'foo' >&3
# Magic Happens here
read bar <&3             # expect $bar == "foo"
echo $?                  # expect "0"
exec 3>&- 
EN

回答 3

Unix & Linux用户

回答已采纳

发布于 2022-02-21 13:49:13

将读描述符的创建与写入描述符分开:

代码语言:javascript
复制
exec 3>file
echo foo >&3
exec 3

3个描述符的表被覆盖,并变为只读表。使用通用描述符是没有意义的。

将描述符号隐藏在变量中:

代码语言:javascript
复制
{ echo foo >&$fd; exec {fd}<&-; } {fd}<>file
{ cat <&$fd; } {fd}<>file
exec {fd}<&-

由于重定向是首先执行的,因此编写了$fd变量,并且在块中已经有了一个值。这里应该注意的是,句柄不是像在ksh93中那样自动关闭的,必须在块的末尾或使用下一个命令显式地关闭句柄(这两个选项都显示了)。准备在下一个bash版本中引入内置变量,从而将其更改为自动关闭行为。使用这种形式的调用,不需要命令exec {fd}<&-。

票数 1
EN

Unix & Linux用户

发布于 2022-02-21 09:01:48

虽然这是一个有趣的问题(但这也是30年来我从来没有用过的壳来做的事情)。你可能试图使用错误的工具。

Unix (UNIX、BSD、MacOS、Gnu/Linux)有管道。管道是一个特殊的文件(不是在辅助存储/磁盘中),它有两个文件描述符。一个用来写作,一个用来阅读。读描述符总是跟在写后面。在读取数据后被废除。

代码语言:javascript
复制
echo a_command | another_command

在启动命令时,有时无法创建管道。在这些情况下,您可以使用命名管道或unix-套接字。

使用其中一个进程创建并销毁unix-套接字。这也是双向的。

可以独立于两个进程创建命名管道。

票数 3
EN

Unix & Linux用户

发布于 2022-02-21 07:58:32

zshksh93lseek()系统调用的内置包装器,但没有bash,因此您需要调用一个单独的实用程序,该实用程序可以在附在fd的开放文件描述上执行lseek()zsh默认安装在macos上,因此,如果您必须使用bash,您可以定义一个包装zsh's sysseek内置的sysseek函数:

代码语言:javascript
复制
sysseek() {
  zsh -c '
    zmodload zsh/system
    sysseek "$@" || syserror -p "$0: "
  ' sysseek "$@"
}

和使用:

代码语言:javascript
复制
sysseek -u 3 0

将fd 3倒带到开头。

对于没有zsh的系统,另一种选择是使用更广泛可用的perl

代码语言:javascript
复制
sysseek() { # args: fd, mode, offset
  perl -e '
    my ($fd, $mode, $offset) = @ARGV;
    open FD, ">&", $fd or die "fd $fd: $!\n";
    seek FD, $mode, $offset or die "seek: $!\n";
  ' -- "$@"
}

和使用:

代码语言:javascript
复制
sysseek 3 0 0

将fd 3倒带到开头。

第二个论点可以是:

  1. 相对于开始寻找(就像sysseek -w startzsh中,默认情况下)。
  2. 寻找与当前职位相关的职位(zsh's sysseek -w current)
  3. 相对于文件的结尾(zsh's sysseek -w end)。
票数 2
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/691539

复制
相关文章

相似问题

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