编辑:
我在下面的评论 sed 's@^@ @' <(f1)是不正确的虽然$BASH_SUBSHELL表明我们与启动处于同一级别,但变量在主脚本中丢失.根据戈登的回答,我测试了f1 > >(sed 's@^@ @'),这似乎工作正常.不过,对于第一种形式,BASH_SUBSHELL不应该是1而不是0吗?
考虑这个小测试
#!/bin/bash
declare -i i=0
function f1()
{
let i++
echo "In f1, SUBSHELL: $BASH_SUBSHELL, i=$i" >&2
}
f1
f1 | sed 's@^@ @'
echo "at end, i=$i"
Run Code Online (Sandbox Code Playgroud)
具有以下输出:
In f1, SUBSHELL: 0, i=1
In f1, SUBSHELL: 1, i=2
at end, i=1
Run Code Online (Sandbox Code Playgroud)
(目的sed只是为了得到一些东西,不要指望它做任何事情,因为f1输出到stderr)
函数f1记录当前的BASH_SUBSHELL和i的当前值
我知道为什么在我们得到的脚本结束时i=1,因为第二次调用是在子shell中,并且子shell 1中i的值丢失了.
我不知道为什么管道的左侧没有在当前的shell中执行
虽然我认为我可以避免这种情况,但sed 's@^@ @' <(f1)
我想知道为什么左侧与主脚本不在同一级别
当我ls -l $(echo file)从括号输入输出(这只是简单的回声)时,将其传递给外部ls -l命令.它等于简单ls -l file.
当我键入时,ls -l (echo file)我们有错误,因为无法嵌套()在外部命令中.
有人可以帮助我理解之间的差异$()和()?
我对bash变量是否导出到子shell以及何时可以通过脚本访问感到困惑.到目前为止,我的经验使我相信bash变量可自动用于子shell.例如:
> FOO=bar
> echo $FOO
bar
> (echo $FOO)
bar
Run Code Online (Sandbox Code Playgroud)
以上似乎表明bash变量可以在子壳中访问.
鉴于此脚本:
#! /usr/bin/bash
# c.sh
func()
{
echo before
echo ${FOO}
echo after
}
func
Run Code Online (Sandbox Code Playgroud)
我知道在当前shell上下文中调用脚本可以访问当前shell的变量:
> . ./c.sh
before
bar
after
Run Code Online (Sandbox Code Playgroud)
如果我在没有"点空间"先例的情况下调用脚本...
> ./c.sh
before
after
Run Code Online (Sandbox Code Playgroud)
...是不是在子shell中调用脚本的情况?如果是这样,并且当前shell的变量可用于子shell(正如我从最初的代码块推断的那样)也是$FOO如此,为什么c.sh在以这种方式运行时不可用?
类似地,为什么在括号内运行$FOO时也不可用c.sh- 我理解为在子shell中运行表达式:
> (./c.sh)
before
after
Run Code Online (Sandbox Code Playgroud)
(如果这个问题没有太多问题:如果" ./c.sh"和" (./c.sh)"都在当前shell的子shell中运行脚本,那么两种调用方式之间有什么区别?)
假设我有一个bash函数
Yadda() {
# time-consuming processes that must take place sequentially
# the result will be appended >> $OUTFILE
# $OUTFILE is set by the main body of the script
# No manipulation of variables in the main body
# Only local-ly defined variables are manipulated
}
Run Code Online (Sandbox Code Playgroud)
我是否可以在子shell中调用该函数作为后台作业?例如:
OUTFILE=~/result
for PARM in $PARAMLIST; do
( Yadda $PARM ) &
done
wait
cat $OUTFILE
Run Code Online (Sandbox Code Playgroud)
你怎么看?
我有一个程序可以同时读取两个输入文件.我想从标准输入中读取该程序.我以为我会用这样的东西:
$program1 <(cat) <($program2)
Run Code Online (Sandbox Code Playgroud)
但我刚刚发现了
cat <(cat)
Run Code Online (Sandbox Code Playgroud)
产生
....
mmap2(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb758e000
read(0, 0xb758f000, 131072) = -1 EIO (Input/output error)
....
cat: -: Input/output error
Run Code Online (Sandbox Code Playgroud)
同样地,
$ cat <(read -n 1)
bash: read: read error: 0: Input/output error
Run Code Online (Sandbox Code Playgroud)
所以...... Linux无法进入read系统调用级别.那很有意思.是bash不是将stdin连接到子壳?:(
这个问题有方法解决吗?我特别需要使用进程替换(... <(...)格式),因为$program1(tail顺便说一下)需要文件,我需要od在标准输入上做一些预处理(with )才能传递给它tail- 我不能只指定/dev/stdin等等.
编辑:
我真正想要做的是从一个文件(另一个进程将写入)读取,同时我也从标准输入读取,所以我可以接受命令等.我希望我能做到
tail -f <(od -An -vtd1 -w1) <(cat fifo)
Run Code Online (Sandbox Code Playgroud)
同时从标准输入和 FIFO中读取并将其放入单个stdout流中,我可以通过awk(或类似的)运行.我知道我可以用任何脚本语言解决这个问题,但我喜欢学习如何 …
据我所知,有两种方法可以在bash函数中创建局部变量:创建子shell或将每个变量声明为local.
例如:
# using local
function foo
{
local count
for count in $(seq 10)
do
echo $count
done
}
Run Code Online (Sandbox Code Playgroud)
要么
# using subshell
function foo
{
(
for count in $(seq 10)
do
echo $count
done
)
}
Run Code Online (Sandbox Code Playgroud)
显然,使用子shell的版本更易于编写,因为您不必关心将所有变量声明为本地(更不用说由getopts等工具创建/导出的(环境)变量).但我可以想象创建一个子shell有一个开销.
那么更好的方法是什么?有哪些优点/缺点?
initiate () {
read -p "Location(s) to look for .bsp files in? " loc
find $loc -name "*.bsp" | while read
do
if [ -f "$loc.bz2" ]
then
continue
else
filcount=$[$filcount+1]
bzip $loc
fi
if [ "$scan" == "1" ]; then bzipint $loc
fi
echo $filcount #Correct counting
echo $zipcount #Correct counting
echo $scacount #Correct counting
echo $valid #Equal to 1
done
echo $filcount #Reset to 0
echo $zipcount #Reset to 0
echo $scacount #Reset to 0
echo $valid #Still …Run Code Online (Sandbox Code Playgroud) 我想知道bash中这两个语法之间有什么区别:( &)和( ) &.
我注意到的唯一区别是,(tty &)将返回"not tty"而(tty) &将返回当前的tty名称,但为什么呢?
举个例子,我应该跑步(setsid startx &)还是(setsid startx) &?
给定一个文件"foo.txt",创建自:
$ seq 1 10 > "foo.txt"
Run Code Online (Sandbox Code Playgroud)
我正在尝试读取文件的第一行和最后一行,并且我开始将文件重定向到子shell,以便命令列表将按顺序使用该文件 - 每个命令都使用来自该点的输入最后一个命令离开了,我想:
$ (head -1; tail -1) < "foo.txt"
1
10
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用临时文件描述符,输出不一样:
$ (head -1; tail -1) < <(seq 1 10)
1
Run Code Online (Sandbox Code Playgroud)
问题:
我不确定要命名的是什么<(seq 1 10),但这个临时文件描述符和常规文件描述符("foo.txt")之间的区别是什么导致子shell执行的行为不同?
如何在不实际创建文件的情况下实现将a重定向"foo.txt"到子shell但没有临时文件的相同行为.
如何确定Bash中当前是否正在使用文件描述符?例如,如果我有一个读取,写入和关闭fd 3的脚本,例如
exec 3< <(some command here)
...
cat <&3
exec 3>&-
Run Code Online (Sandbox Code Playgroud)
什么是确保我不干扰脚本运行之前可能设置的描述符的其他目的的最佳方法?我需要将整个脚本放在子shell中吗?
bash ×10
subshell ×10
function ×2
shell ×2
unix ×2
variables ×2
background ×1
io ×1
linux ×1
local ×1
pipe ×1
redirect ×1
stdin ×1
subprocess ×1
while-loop ×1