比较分隔字段

比较分隔字段

我的文件中有两个字段:学生和教师。它们由分号分隔,我想找到哪些单身学生有两个不同的老师。

jdoe;ateacher
jdoe;bteacher
jsmith;cteacher
bbrown;dteacher
dholden;eteacher

将传送至:

jdoe;ateacher
jdoe;bteacher

我怎样才能用外壳做到这一点?

笔记:这是家庭作业。我不是在寻找确切的答案,只是不确定从哪里开始。我已经解析并将其从文件中传输到我需要的字段中,现在我只需要找到重复的内容,但我不知道如何开始。

答案1

假设您显示的文件格式是严格的,如果学生有 2 个不同的老师,则该学生只会显示两次,并且给定学生的条目始终彼此相邻,您可以使用此命令来查找所有重复项。该文件中的重复项表示一个学生有多个老师,因此我们可以忽略这一事实。

例子

$ awk -F';' '{ print $1 }' file | uniq -d
jdoe

这将解析文件file并使用awk字段分隔符开关将其分割-F';'。然后我们指示awk仅打印第一个字段,即学生的姓名。然后,我们将该输出通过管道传输uniq并告诉它仅打印重复的行。

然后,我们可以在 for 循环中使用此信息,并且仅打印上面命令返回的列表中包含学生的行。以下是循环的粗略结构:

$ for i in $(..cmd from above..); do 
    ... print lines that contain "$i" ...
done

在这里,我们获取初始命令的输出awk,并在 Bash shell 中使用 for 循环对其进行循环。这通常是大多数人刚开始时会采取的方法。

例子

$ for i in $(awk -F';' '{ print $1 }' file | uniq -d); do \
    grep "^$i;" file; done
jdoe;ateacher
jdoe;bteacher

这种方法虽然有效,但也存在一些问题。如果文件名包含空格,此方法将失败。您可以使用 while 循环切换到更复杂的方法。

$ while read; do grep "^$i;" file; done \
    < <(awk -F';' '{ print $1 }' file | uniq -d)
jdoe;ateacher
jdoe;bteacher

在这里,我们从命令中获取输出并将其传递到 while 循环中,如下所示:

$ while read; do .... ; done < <(...our command...)

这样做的好处是可以使用此表示法创建临时文件,并将所有结果作为行传递到 while 循环中。因此,该read命令现在只需解析由换行符分割的结果,而不是 for 循环实现中的空格。

< <(...command...)

例子

以下是 for 循环和空格所发生的情况:

$ for i in jdoe john smith jjill;do echo "$i"; done
jdoe
john
smith
jjill

相关内容