posix shell expansion,non-interactiveshell模仿interactive,命名管道fifo

摘要

posix shell 判断变量是否存在 使用所有shell sh bash zsh fish

subprocess popen 交互式 shell interactive shell

posix shell 判断变量是否存在 使用所有shell sh bash zsh fish

代码

例子中, PYTHONPATH不存在但是PATH存在.

ver 1

$ if [ -z ${PYTHONPATH:+exist_and_not_empty} ]; then return 1; else return 0; fi
$ echo $?
1
$ if [ -z ${PATH:+exist_and_not_empty} ]; then return 1; else return 0; fi
$ echo $?
0

ver 2

$ echo ${PATH:?not_exist_or_empty}
# ...
$ echo $?
0
$ echo ${PYTHONPATH:?not_exist_or_empty}
zsh: PYTHONPATH: not_exist_or_empty
$ echo $?
1

原理

参考 stackoverflow.com/a/16753536

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |       parameter      |     parameter   |    parameter    |
|   in script:       |   Set and Not Null   |   Set But Null  |      Unset      |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word}  | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word     | assign word     |
| ${parameter=word}  | substitute parameter | substitute null | assign word     |
| ${parameter:?word} | substitute parameter | error, exit     | error, exit     |
| ${parameter?word}  | substitute parameter | substitute null | error, exit     |
| ${parameter:+word} | substitute word      | substitute null | substitute null |
| ${parameter+word}  | substitute word      | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+


+--------------------+----------------------+-----------------+-----------------+
|   Expression       |  When FOO="world"    |  When FOO=""    |    unset FOO    |
|   in script:       |  (Set and Not Null)  |  (Set But Null) |     (Unset)     |
+--------------------+----------------------+-----------------+-----------------+
| ${FOO:-hello}      | world                | hello           | hello           |
| ${FOO-hello}       | world                | ""              | hello           |
| ${FOO:=hello}      | world                | FOO=hello       | FOO=hello       |
| ${FOO=hello}       | world                | ""              | FOO=hello       |
| ${FOO:?hello}      | world                | error, exit     | error, exit     |
| ${FOO?hello}       | world                | ""              | error, exit     |
| ${FOO:+hello}      | hello                | ""              | ""              |
| ${FOO+hello}       | hello                | hello           | ""              |
+--------------------+----------------------+-----------------+-----------------+

subprocess popen 交互式 shell interactive shell

subprocess

如果 p = Popen(…)

p.communicate 无法交互式运行! 只要cmd执行完, 整个进程都结束了!

p.stdin.write p.stdout.read p.wait 也无法交互式运行! wait导致整个进程都结束了!

实际上 p.communicate = p.stdin.write p.stdout.read p.wait

sh只能执行固定数量的shell命令. 但是, 终端的交互式shell是怎样实现的呢? 请看!

$ while true
> do read line
> $line
> done

怎样写成一行呢?

while true do read line $line done # 大错特错!

sh报错: 没有do

可是我们明明写了do?

while true; do read line; $line; done; # 😀👍

原来do也类似一条命令! 要么以;结尾要么以\n结尾!

sh中大致有三种命令

  • 外存二进制镜像/解释器及脚本 which ls/usr/bin/ls
  • 内置命令 which cdcd: shell built-in command
  • 保留关键字 which esacesac: shell reserved word

esac这种碳基生物整不出的活儿,竟然是为了防止保留字吃掉我们的变量名,他真的我哭死…😵

do是一条命令 要么以;结尾要么以\n结尾 $line可以看作do的参数
do是一条命令 要么以;结尾要么以\n结尾 $line可以看作do的参数
do是一条命令 要么以;结尾要么以\n结尾 $line可以看作do的参数

# leaf @ machine in ~ [16:33:52]
$ mkfifo p q

# leaf @ machine in ~ [16:34:02]
$ sh -c 'while true; do read line && $line; done;' < p > q &
[1] 299

# leaf @ machine in ~ [16:34:09]
$ cat q &
[2] 308

# leaf @ machine in ~ [16:34:17]
$  echo 'pwd' > p
/home/leaf

# leaf @ machine in ~ [16:34:24]
$ echo 'ls' > p
bin
mine
p
q

为什么要手动构造管道呢? 因为默认构造的subprocess.PIPE是unnamed pipe

在这里插入图片描述

# leaf @ machine in ~ [16:47:34]
$ bash -c 'n=0; while (($n<=3)); do echo $n; n=$((n+1)); sleep 1; done;' | dd
0
1
2
3
0+4 records in
0+1 records out
8 bytes copied, 4.00424 s, 0.0 kB/s

注意 4.00424 s 这说明匿名管道 写端完成 读端才可读 因此 subprocess.PIPE 无法实现交互式命令!

⚠ & 和 ; 都是shell的结束符, 二者至多出现一个.
如果两个结束符之间为空, bash和zsh可能不报错, 但是/bin/sh会报错!

sh -c 'while true; do read line && $line; done;' < p > q & ; ×

sh -c 'while true; do read line && $line; done;' < p > q &

怎样处理异步通信的问题呢?比方说 sleep 1 ;这就是操作系统、分布式系统的内容了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值