【问题标题】:Combine multiple files into single file in unix shell scripting在 unix shell 脚本中将多个文件合并为单个文件
【发布时间】:2016-02-27 04:54:59
【问题描述】:

我想将 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

请帮我解决这个问题。

【问题讨论】:

  • 对文件的组合方式是否有任何额外的限制,例如排序?因为如果没有,'cat' 和 '>'/'>>' 输出重定向应该可以满足您的需要。
  • 我认为 Demon 想将两个文件横向而不是纵向合并。
  • @Sung:不是根据样本数据(现在问题已正确格式化,这一点更加明显)。
  • 确实如此。那么解决方案就更简单了。

标签: shell unix


【解决方案1】:

这样的脚本:

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

应该可以解决问题。 Sort 将对两个文件的连接(脚本的两个第一个参数)进行排序,将结果传递给uniq,它将删除相邻的相同行并将结果推送到第三个文件(脚本的第三个参数)。

【讨论】:

  • ++ 表示不需要cat(您可以将多个文件直接传递给sort);考虑使用sort -u 而不是涉及uniq
【解决方案2】:

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

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) 作为键(索引)填充,每个元素都是按需创建的。

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

  • 1234563应用减量 (++),元素的结果值为1
  • 以后只要遇到该行的副本,数组元素的值就会递增。
  • 最终效果是,对于任何给定的输入行,!seen[$0]++ 如果第一次看到输入行,则返回 true,而 false em> 为其每个重复项(如果有)。请注意,++,由于是一个-增量,仅在评估!seen[$0] 之后应用

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

  • 整体效果是:行按输入顺序打印,但有重复的行只打印第一个实例,有效消除重复。

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

【讨论】:

  • 感谢您的回复,但我想将文件名作为参数传递给脚本,因为如果在组合文件中找到重复记录,我会想要消除重复记录。
  • 基本上意味着在选择要合并的文件1和文件2之后,我想在我尝试时将这两个名称沿着合并文件的名称(由我指定的名称)传递给脚本对合并文件中的数据进行重复数据删除。
【解决方案3】:

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

cat file* > combined_file

编辑:假设您将文件名作为参数传递,脚本会执行相同的操作

#!/bin/sh
cat $1 $2 $3 | uniq > combined_file

现在您可以根据需要显示组合文件。或者直接访问。

【讨论】:

  • 感谢您的回复,但我想将文件名作为参数传递给脚本,因为如果在组合文件中找到重复记录,我会想要消除重复记录。基本上意味着在选择要组合的文件 1 和文件 2 之后,我想将这两个名称沿着组合文件的名称(由我指定的名称)传递给脚本,同时我尝试对数据进行重复数据删除合并文件。
  • uniq 只排除相邻的相同行,需要先排序。数据可以排序吗?
  • 另外,参数引用应该是双引号。
猜你喜欢
  • 1970-01-01
  • 2021-11-08
  • 1970-01-01
  • 2013-01-09
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
  • 2013-09-06
相关资源
最近更新 更多