If you don't need to set global variables, or are willing to use named pipes, you can use:
$NAMED_PIPE="/tmp/mypipe"
mkfifo $NAMED_PIPE
command | # piped into while read, command can be an event watcher
while read -r foo bar; do
MY_VAR="$foo"
echo "$MY_VAR" # This works
echo "MY_VAR" > "$NAMED_PIPE" &
done
echo "$MY_VAR" # This doesn't work
cat "$NAMED_PIPE" # This works
If you need to set global variables, you can use the following in bash:
while read -r foo bar; do
MY_VAR="$foo"
echo "$MY_VAR" # This works
done < <(command) # command can be an event watcher
echo "$MY_VAR" # This works
In POSIX sh, you can do the following, but it doesn't work with continuous input (seems to just hang):
while read -r foo bar; do
MY_VAR="$foo"
echo "$MY_VAR" # Works as long as command doesn't produce continuous output
done <<-EOF
$(command)
EOF
echo "$MY_VAR" # Works as long as command doesn't produce continuous output
Is there a solid way to parse an event watcher (e.g. xev, xprop -spy) in POSIX sh and be able to set global variables? Named pipes seem difficult to use portably and safely.
The named pipe is the solution, but you are using it in the wrong place.
NAMED_PIPE="/tmp/mypipe"
mkfifo "$NAMED_PIPE"
command > "$NAMED_PIPE" &
while read -r foo bar; do
MY_VAR="$foo"
echo "$MY_VAR"
done < "$NAMED_PIPE"
echo "$MY_VAR"