是否可以提前强制zsh参数扩展?
问题:我目前在zsh脚本中有一个这种结构的管道是否可以提前强制zsh参数扩展?,zsh,Zsh,问题:我目前在zsh脚本中有一个这种结构的管道 a|b|c|d|e >result 我想对此进行修改,以便如果某个变量$v不是空的,那么文件result应该只包含那些与$v中的regexp匹配的行。以下是三种显而易见的方法: # I don't like this because it causes an extra (possibly large) # temporary file a|b|c|d|e >result if [[ -n $v ]] then mv result
a|b|c|d|e >result
我想对此进行修改,以便如果某个变量$v不是空的,那么文件result
应该只包含那些与$v中的regexp匹配的行。以下是三种显而易见的方法:
# I don't like this because it causes an extra (possibly large)
# temporary file
a|b|c|d|e >result
if [[ -n $v ]]
then
mv result result1
grep -E $v result1 >result
rm result1
fi
或
或:
我真正想要的是:
# This does not work
if [[ -z $v ]]
then
filter=
else
filter='|grep -E $v'
fi
a|b|c|d|e ${(z)filter} >result
这不起作用,因为Zsh首先识别各个命令,然后计算参数,因此将我的filter命令作为参数传递给程序e
我知道我也可以通过基于$v的值构建命令行,然后使用eval
来解决这个问题,但我也不喜欢这样,因为在实际情况下,所有涉及的程序都会获得多个参数,并进行大量引用,而将其置于一种在评估时仍然有效的形式也很容易导致错误
在生成命令之前,是否有其他方法强制对$filter进行求值?我使用的是Zsh 5.3。解决方案可能是使用fifo和文件描述符,比如
# open fd 3
if [[ -z $v ]]; then
exec 3> result
else
fifo=/tmp/fifo$$
mkfifo "$fifo"
grep -E "$v" "$fifo" >result & grep_pid=$!
exec 3>"$fifo"
end
a|b|c|d|e >&3
# close fd3 and clean
exec 3>&-
if [[ -n $v ]]; then
wait $grep_pid
rm "$fifo"
fi
您只需将管道插入if
语句即可。您可以复制e
:
a | b | c | d | e |
if [[ -z $v ]]; then
e
else
e | grep -F $v
fi > result
或者,如果需要额外的cat
命令将输出通过管道,则将e
拉出(如果):
a | b | c | d | e |
if [[ -z $v ]]; then
cat
else
grep -F $v
fi > result
或者,您可以使用参数扩展来定义“接受任何东西”模式,以便与grep
一起使用
a | b | c | d | e | grep -F ${v:-.} > result
有时grep-E
有时grep-F
这是一个打字错误,还有另一个解决方案,但总是运行grep:grep-E“${v:-^}”
a | b | c | d | e |
if [[ -z $v ]]; then
cat
else
grep -F $v
fi > result
a | b | c | d | e | grep -F ${v:-.} > result