【问题标题】:grep on one file and sort matches to several output files对一个文件进行 grep 并将匹配项排序到多个输出文件
【发布时间】:2017-07-17 22:31:11
【问题描述】:

我的问题涉及以下方面: 我有文件:

    FileA:
Peter Programmer
Frank Chemist
Charles Physicist
John Programmer
Alex Programmer
Harold Chemist
George Chemist

我现在从 FileA 中获取所有作业信息并将其保存到唯一列表 (FileB)。

  FileB:
Programmer
Chemist
Physcist

(假设 FileA 继续存在更多人员和冗余信息)

我现在要做的是从 FileA 中获取所有作业类,并为每个作业类创建一个新文件,这样最后我就有了:

FileProgrammer
Peter Programmer
John  Programmer
Alex  Programmer

FileChemist
Frank Chemist
Harold Chemist
George Chemist

FilePhysicist
Charles Physicist

我想grep Jobs File 列表中的作业名称模式,并为其他原始文件中存在的每个作业名称创建一个新文件。

所以实际上,我的列表中有 56 个唯一元素,而原始文件有几列(制表符分隔)。

到目前为止,我所做的是:

cut -f2 | sort | uniq > Jobs
grep -f(tr '\t' '\n' < "${Jobs}") "${FileA}" > FileA+"${Jobs}"

我假设在每个新模式匹配上都会创建一个新文件,但我意识到它只会复制文件,因为没有增量或迭代文件创建。

由于我在 bash 方面的经验还有待深入开发,希望大家能帮助我。提前致谢。

@更新: 输入文件如下所示:

4   23454   22110   Direct  +   3245    Corrected
3   21254   12110   Indirect    +   2319    Paused-@2
11  45233   54103   Direct  -   1134    Not-Corrected

基本上,我希望所有在“已更正”的第 7 列中具有状态的所有内容都位于名为“已更正”的文件中,因此对于第 7 列的每个唯一值。

【问题讨论】:

  • 你为什么要用grep做这个?可以用awk吗?
  • 当然,我可以使用 awk - 我只是不太熟悉 awk 在循环上下文中的功能。我尝试了一些 awk 循环,但有些失败。
  • Awk试试我的回答

标签: bash loops awk grep


【解决方案1】:

答案渴望需要Awk,这是你的做法,

awk '{unique[$2]=(unique[$2] FS $1)}\
END  {for (i in unique) { \
        len=split(unique[i],temp); \
        for (j=1;j<=len;j++) print temp[j],i > "File"i".txt"} }' \
file

这个想法是创建一个 hash-map,使用unique[$2]=(unique[$2] FS $1),字面意思是,将$2 视为数组unique 的索引,并从$1 附加值,所以在输入文件的每一行处理结束时,数组看起来像这样,

# <key>  <value(s)>
Chemist  Frank Harold George
Physicist  Charles
Programmer  Peter John Alex

END 子句在处理完所有行之后执行,因此从构造的数组中,使用在单个空白处拆分的split() 函数,我们将数组值的内容存储到数组temp ,而len 包含拆分后产生的元素数。

每个哈希索引的循环和每个拆分元素的值都被打印并存储在文件中。

【讨论】:

  • 谢谢伊尼安。快速提问:您的 Awk 脚本假定要搜索的文件每行只包含一个名称,对吗?我只是以此为例,但实际上我有一个 7 列宽的文件,可以按 grepawk 进行“排序”。如果我创建一个哈希映射,我将不得不创建一个数组哈希,每个键分配给一个由数组表示的行,正确吗?文件示例:27 Hatfield Peter London 4 8 Programmer - Tab 是分隔符。
  • 提供您对问题的实际输入。
【解决方案2】:

您可以在循环中使用grep 来实现:

for i in $(cat FileB); do grep $i$ FileA >> File$i; done

请注意,在您的问题的 FileA 中您写了“Physicist”,而在 FileB 中您写了“Physcist”,所以它们不匹配。无论如何,如果您正确编写它们,上面的命令将起作用。

【讨论】:

  • 谢谢,这条线路运行良好。抱歉打错了。唯一的问题是 grep 在匹配模式时似乎很粗糙。例如,如果工作是 Chemist-Biochemist,grep 会将其与其他 Chemist 一起放入文件中,而不是创建另一个 Chemist-Biochemist 文件。关于如何纠正的任何进一步建议?我看到提出了 Awk,但不幸的是我很难理解 Awk 代码。
  • @chrys:哪一部分,你不明白?试图解释那里的每一点。
  • @chrys 我已经编辑了命令来强制字符串的结尾被 grep 以避免这种情况。检查它现在是否有效。
猜你喜欢
  • 2017-07-02
  • 2017-06-15
  • 2016-06-27
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 2021-12-22
  • 2012-02-02
  • 2012-06-04
相关资源
最近更新 更多