[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: bash: request for a way to return variables to the parent of a subsh
From: |
Richard Neill |
Subject: |
Re: bash: request for a way to return variables to the parent of a subshell |
Date: |
Wed, 23 Jul 2008 05:01:21 +0100 |
User-agent: |
Thunderbird 2.0.0.14 (X11/20080629) |
Dear Eric,
Thank you for your helpful answer. I'd understood that bash *doesn't*
pass info back from the child to the parent, but I didn't realise that
it was fundamentally *impossible* to do in Unix. I guess that tempfiles
would do it - though that's rather ugly.
Is there any way to use "read" to iterate over its standard input
without creating a subshell? If it's of interest, the actual part of
the script I use is below - the aim is to parse the output of "ffmpeg
-formats" to see whether certain codecs are supported by that build.
Regards,
Richard
--------------------------------------------------------------
#Does this version of FFMPEG support the relevant file format? Exit
#if not. Arguments: $1='file' or 'codec'; $2='E','encode' or
# 'D','decode', $3=format/codec_name
#Example: check_ffmpeg_format file D ogg
#The output of `ffmpeg -formats` has section headings such as
#"File formats", and each section is delimited by a blank line.
#The first part of the line contains letters DEA(etc) depending
#on whether the codec/file is supported
#for reading (decoding) and/or writing (encoding).
function check_ffmpeg_format_support(){ .
local filecodec=$1
local decodeencode=$2
local filecodec_name=$3
if [ $filecodec == 'file' ];then
local start_trigger='File formats:'
local end_trigger=''
local terminator='\ +'
local filecodec_txt='file format'
else
local start_trigger='Codecs:'
local end_trigger=''
local terminator='$'
local filecodec_txt='with codec'
fi
if [ $decodeencode == 'decode' -o $decodeencode == 'D' ];then
local decodeencode='D[A-Z ]*'
local decodeencode_txt='decoding'
else
local decodeencode='[A-Z ]?E[A-Z ]*'
local decodeencode_txt='encoding'
fi
local matchme='^\ *'$decodeencode'\ +'$filecodec_name'\ *'$terminator
local relevant=false
#Warning: this pipe has the effect of a subshell. Variables are
#set inside the pipeline, and cannot be accessed outside it.
#Search between trigger points.
ffmpeg -formats 2>/dev/null | while read line ; do
if [[ $line =~ $start_trigger ]]; then
relevant=true
fi
if [[ $line == $end_trigger ]]; then
relevant=false
fi
if [ "$relevant" == true ];then
if [[ $line =~ $matchme ]];then #Regex match.
exit 2
fi
#Exit the '| while read...' part, and return $? so we
#know the result.
fi
done
if [ $? != 2 ]; then
echo -e "ERROR: the installed version of 'ffmpeg' was built
without support enabled for $decodeencode_txt $filecodec_txt
'$filecodec_name'.\n"
exit 1
fi
}
--------------------------------------------------------------
Eric Blake wrote:
According to Richard Neill on 7/22/2008 8:04 PM:
| This prints "Match-1", but does not print "Match-2".
|
| The only way to get data out of the read-subshell is by something like
| "exit 2", and looking at $?
You can also use files. The position within a seekable file is preserved
from child to parent, but once you are using files, you might as well go
with the file contents.
| It's already possible to export a variable into the environment, and for
| subshells to inherit variables from the main script. Do we need a new
| keyword to achieve the reverse? Is there any way to make sure that
| variables defined at [a] can be made to still exist at [b] ?
A new keyword is insufficient. This is something that is fundamentally
not provided by Unix systems - short of using the file system, there
really isn't a way to pass arbitrary information from a child process back
to the parent.
But maybe the 'source' builtin is what you are looking for, to execute a
script in the same context rather than forking off a child.