Bash 无法识别存储在MAPFILE元素中的文件名的联接

Bash 无法识别存储在MAPFILE元素中的文件名的联接,bash,join,Bash,Join,我试图通过共享查找列(第一列)连接65个文件。我正在命令行上测试部分代码,并且在作为JOIN输入的MAPFILE元素方面存在问题。我尝试了几种不同的方法来回显MAPFILE的元素,但都没有成功。当我用元素所代表的文件名替换元素时,它工作正常。如何将MAPFILE的元素传递给JOIN cat list.txt | ( mapfile -t; echo "${MAPFILE[@]}" ) | join -11 -21 -a1 -a2 -o1.1,1.2,2.2 -e0 ${MAPFILE[1]} $

我试图通过共享查找列(第一列)连接65个文件。我正在命令行上测试部分代码,并且在作为JOIN输入的MAPFILE元素方面存在问题。我尝试了几种不同的方法来回显MAPFILE的元素,但都没有成功。当我用元素所代表的文件名替换元素时,它工作正常。如何将MAPFILE的元素传递给JOIN

cat list.txt | ( mapfile -t; echo "${MAPFILE[@]}" ) | join -11 -21 -a1 -a2 -o1.1,1.2,2.2 -e0 ${MAPFILE[1]} ${MAPFILE[2]} >countmatrix.txt
尝试的其他战略:

cat list.txt | ( mapfile -t; echo "${MAPFILE[@]}" ) | (file1=$(echo ${MAPFILE[1]}); file2=$(echo ${MAPFILE[2]})) | join -1 -2 -a -o1.1,1.2,2.2 -e0 $file1 $file2 >countmatrix.txt

cat list.txt | ( mapfile -t; echo "${MAPFILE[@]}" ) | (file1=$(echo ${MAPFILE[1]}); file2=$(echo ${MAPFILE[2]}); join -11 -21 -a1 -a2 -o1.1,1.2,2.2 -e0 <(sort $file1) <(sort $file2) >countmatrix.txt)
cat list.txt |(mapfile-t;echo“${mapfile[@]}”)|(file1=$(echo${mapfile[1]});file2=$(echo${mapfile[2]}))| join-1-2-a-o1.1,1.2,2.2-e0$file1$file2>countmatrix.txt

cat list.txt |(mapfile-t;echo“${mapfile[@]}”)|(file1=$(echo${mapfile[1]});file2=$(echo${mapfile[2]});join-11-21-a1-a2-o1.1.2,2.2-e0您正在子shell和指定变量中执行
mapfile
${MAPFILE[@]}
无法从父进程访问

请尝试以下方式:

cat list.txt | ( mapfile -t; echo "${MAPFILE[@]:0:2}" ) | xargs join -11 -21 -a1 -a2 -o1.1,1.2,2.2 -e0 > countmatrix.txt
考虑到这种情况,
list.txt
中定义的文件名包含空格 和/或其他特殊字符,更安全的说法是:

cat list.txt | ( mapfile -t; printf "%s\0" "${MAPFILE[@]:0:2}" ) | xargs -0 join -11 -21 -a1 -a2 -o1.1,1.2,2.2 -e0 > countmatrix.txt

两次引用的尝试都失败,因为它们尝试读取一个子外壳中的映射文件,并使用管道的第二个子外壳中的值。在sh*外壳中,变量从父子外壳传递到子子子外壳。管道的每个元素都在作为主外壳子外壳的子外壳中执行

因此,来自管道一部分的变量对管道的其他部分不可用(例如
a=5 | echo$a
将不起作用)

在这种情况下:

  • (mapfile…)在子shell中执行,读取mapfile
  • “join”在单独的不相关子shell中执行,不能使用MAPFILE
  • 简单的解决方案是读取主shell(或中间子shell)中的映射文件,如下所示

    # Read MAPFLE
    mapfile -t < list.txt
    # EXecute join, use  MAPFILE
    join -11 -21 -a1 -a2 -o1.1,1.2,2.2 -e0 ${MAPFILE[1]} ${MAPFILE[2]} >countmatrix.txt
    
    #阅读MAPFLE
    映射文件-tcountmatrix.txt
    
    表面上,不需要将任何内容通过管道传输到join命令中,该命令使用命名文件进行输入(忽略stdin)


    “真正”的解决方案(65个文件)应该在循环中包含连接,而不是单个连接。

    可以显示一些示例输入和输出,比如2或3个文件,而不是65个文件吗?输入是list.txt,这是一个文件名列表,每个文件名都出现在新行上。由于连接抛出额外的操作数错误,代码的第一行没有输出。其他策略是utput countmatrix.txt为空文件。感谢您对子进程和父进程的解释。xargs失败,因为MAPFILE长度超过2个元素,join将其他元素解释为额外操作数。明白。我已相应地更正了我的答案。但是,如果您要参考剩余的(第三个或更高版本)
    ${MAPFILE[@]}
    随后,最好在父级(当前)中执行
    MAPFILE
    以@dash-o写入的方式处理。感谢您的详细解释。在最终脚本中,连接存在于映射文件数组内容的for循环中。在运行最终脚本之前,我试图在命令行上验证脚本组件,但遇到此错误。