在 bash 中连接两个文本文件以获得与两列匹配的输出

在 bash 中连接两个文本文件以获得与两列匹配的输出

需要在 Bash 脚本中将这两个 TXT 连接成一个,如下所示。你能帮忙吗

学生TXT文件

123456 John Doe
345678 John P. Doe
987654 John Public Doe

课程文本文件

EECS2021 John Doe
EECS2021 John P. Doe
EECS2031 John Doe
EECS4201 John Doe

最终的 TXT 应该包含人员和为他分配的课程。例如:-

Person          courses
John Doe        EECS2021 | EECS2031 | EECS4201
John P. Doe     EECS2021 
John Public Doe NoCourses

我尝试了这个脚本,但仍然无法得到输出。

#!/bin/sh
persons=`cat T1.txt`
courses=`cat T2.txt`
echo "$persons"
echo "$courses"
linecountf1=$(wc -l T1.txt | awk '{print $1}')
linecountf2=$(wc -l T2.txt | awk '{print $1}')
i=1
y=1

echo "$persons" | while read line
do
   name1=$(cat T1.txt | awk -F" " '{print $2" " $3" " $4" " $5" " $6}' | sed -n '$i p')
   while [ $linecountf1 = $linecountf2 ]
   do
        name2=$(cat T2.txt | awk -F" " '{print $2" " $3" " $4" " $5" " $6}' | sed -n '$y p')
        if [ "$name1" = "$name2" ]
                then
                        echo "It matching"
                        gdc=$(cat T2.txt | awk -F" " '{print $1}' | sed -n '$i p')
                fi
   done
done



echo "John Doe Registered courses - $gdc"
echo "John P. Doe Registered courses -"
echo "John Public Doe Registered courses -"

谢谢

答案1

如果输出顺序无关紧要,则以下awk程序应该可以工作:

awk 'FNR==NR{sub(/^[^ ]* +/,""); courses[$0]; if (length($0)>max) max=length($0); next}
     {course=$1; sub(/^[^ ]* +/,"");
      if (courses[$0]) courses[$0]=courses[$0] " | " course; else courses[$0]=course}
     END{
       printf "%- *s Courses\n",max, "Person";
       for (p in courses) {printf "%- *s %s\n",max,p,courses[p] ? courses[p] : "NoCourses"}
     }' students.txt courses.txt 

对于您的输入示例,它将生成(在 GNU 上awk):

Person          Courses
John Public Doe NoCourses
John P. Doe     EECS2021
John Doe        EECS2021 | EECS2031 | EECS4201

解释

  • 在处理第一个文件时(由FNR每个文件行计数器 表示,等于NR全局行计数器),我们只需填充一个数组courses,其中“索引”是学生姓名,并且该值仍为空。为此,我们使用该sub()函数从行中删除学生 ID,以便仅保留学生姓名($0现在仅包含学生姓名) - 这是必要的,因为学生姓名可以包含任意数量的空格,因此通常的“在空间进行场分割”并不能帮助我们提取名称。

    同时,记录最长的名称长度,max以便稍后美化输出。

  • 处理第二个文件时,将课程编号(第一个空格分隔的字段)保存在临时变量中course,然后再次从行中删除它,以便仅保留学生姓名。然后,在数组中查找学生姓名courses,如果已经存在关联值(即courses[$0]不为空),则将课程名称附加到现有值中,并以 分隔|。否则,将该值设置为当前课程名称。

  • 处理两个文件后(条件END),打印列标题 - 格式化以容纳最长的学生姓名 - 然后迭代学生课程数组并打印每个条目的学生姓名和相关课程(for (p in courses)意味着迭代所有“数组索引” = 中的学生姓名courses;这是我无法保证输出顺序的部分 - 取决于您的awk版本)。

相关内容