在unix shell脚本中将多个文件合并为单个文件

时间:2016-02-27 04:55:00

标签: shell unix

我想将具有相同列和数据类型的3个(比较)文件的数据合并到一个文件中,我可以进一步用它进行处理。
目前我必须一个接一个地处理文件。所以,我正在寻找一个解决方案,我可以在脚本中编写,将所有文件合并为一个文件 例如:
文件1:

mike,sweden,2015
tom,USA,1522
raj,india,455

文件2:

a,xyz,155
b,pqr,3215
c,lmn,3252

预期的合并文件3:

mike,sweden,2015
tom,USA,1522
raj,india,455
a,xyz,155
b,pqr,3215
c,lmn,3252

请帮助我。

3 个答案:

答案 0 :(得分:1)

脚本如:

#!/bin/sh
sort "$1" "$2" | uniq > "$3"

应该做的伎俩。 Sort将对两个文件的串联进行排序(脚本的两个第一个args),将结果传递给uniq,这将删除相邻的相同行并将结果推送到第三个文件(脚本的第三个arg)。 / p>

答案 1 :(得分:0)

回答问题的原始形式: 正如@Lars在对该问题的评论中所述,看起来像输入文件的简单连接,这正是cat的用途(甚至命名< / em> for):

cat file1 file2 > file3

要满足您稍后添加的要求:

#!/bin/sh

# Concatenate the input files and sort them with duplicates removed
# and save to output file.
cat "$1" "$2" | sort -u  > "$3"

但请注意,您可以将连接和排序合并为一个步骤,如Jean-Baptiste Yunès's answer所示:

# Sort the input files directly with duplicates removed and save to output file.
sort -u "$1" "$2" > "$3"

请注意,使用sort是消除重复的最简单方法如果您不想要排序,则必须使用其他更复杂的方法,例如使用 awk

#!/bin/sh

# Process the combined input and only 
# output the first occurrence in a set of duplicates to the output file.
awk '!seen[$0]++' "$1" "$2" > "$3"

!seen[$0]++是一种常见的awk成语,只能打印一组副本中的第一个:

  • seen是一个关联数组,每个输入行($0)都填充为键(索引),每个元素都是按需创建的。

  • 这意味着来自一组重复项(即使不相邻)的所有行都引用相同的数组元素。

  • 在数值上下文中,awk的变量值和数组元素是隐式0,因此当第一次看到的给定输入行时并且应用了后递减(++),元素的结果值为1

  • 每当遇到该行的副本时,数组元素的值都会递增。
  • 对于任何给定的输入行!seen[$0]++,如果在第一个时间看到输入行,则 true 的净效果为<每个重复项的em> false ,如果有的话。请注意,++由于是帖子 -increment,仅在评估 !seen[$0]后才会应用

    • ! 否定 seen[$0]的值,导致值0 - 在布尔上下文中为 false 返回 true ,以及返回 false 的任何非零值(遇到重复项)。
  • !seen[$0]++awk中所谓的模式的实例 - 针对输入行评估的条件,用于确定关联的操作(一段代码)应该被处理。在这种情况下,没有操作,在这种情况下awk隐式只是打印输入行,如果!seen[$0]++表示 true

    < / LI>
  • 整体效果是:行按输入顺序打印,但对于带有重复项的行,只打印第一个实例,有效地消除重复。

请注意,对于具有较少重复项的大型输入文件,此方法可能会出现问题,因为大多数数据必须保存在内存中。

答案 2 :(得分:0)

如果您的文件命名约定相同(例如file1,file2,file3 ... fileN),那么您可以使用它来组合所有。

cat file* > combined_file

编辑:假设您将文件名作为参数

传递,脚本也会这样做
#!/bin/sh
cat $1 $2 $3 | uniq > combined_file

现在,您可以根据需要显示combined_file。或者直接访问它。