fish 脚本中的嵌套代码块和子外壳

Nested code blocks and subshells in fish script

我正在努力将一个 bash script 变成鱼。我已经做了大部分,但是有一个复杂的部分有几个嵌套和链接的块。

考虑以下 bash 中的简化部分。逻辑和命令不要读太多,按照结构,注意()中的两个subshell重定向到comm.

dummy () {
    {
    comm -13 \
        <(cat $CACHEDLIST | gawk  '{print }' FS='\t' OFS='\t') \
        <(cat $PDFLIST | gawk '{print }' FS='\t' OFS='\t') \
    } | fzf
}

我将所有 {} 个块转换为 begin; end。然后有两个 subshell 块重定向到 comm -13,我也将其转换为 begin; end fish 块,整个块通过管道传输到 fzf。所以最终结果很简单:

function dummy
    begin
        comm -13 \
             <begin; echo "Arg1"; end \
             <begin; echo "Arg2"; end \
    end | fzf
end

如果我 运行 shell 中的这个小片段,我得到:

(line 7): 'end' outside of a block

怎么会?我唯一的猜测是不尊重行的延续,因为问题肯定出在两条 <begin; ...; end \ 行上。

一种翻译方法是使用显式命名管道代替 bash 的进程替换构造。请注意 comm 两边的大括号不是必需的,因为命令组中只有一个命令。这意味着 fish 函数中少了一对开始-结束。

function dummy
    begin
        mkfifo p1 p2
        gawk '{print }' FS='\t' OFS='\t' "$CACHEDLIST" > p1 &
        gawk '{print }' FS='\t' OFS='\t' "$PDFLIST" > p2 &
        comm -13 p1 p2 | fzf
        rm p1 p2
    end

(您可能希望通过在临时目录中创建 p1p2 并确保在出现任何错误时将其删除来使其更加稳健。)

看来你已经解决了你的问题,但为了后代:

function dummy 
    comm -13 (cut -f1 $CACHEDLIST | psub) (cut -f1 $PDFLIST | psub) | fzf
end