【问题标题】:UNIX scripting - Changing a field of one file, based on matching a condition from a field in a second fileUNIX 脚本 - 根据匹配第二个文件中字段的条件来更改一个文件的字段
【发布时间】:2015-08-12 09:02:32
【问题描述】:

我有两个(巨大的~100 GB)文件,多个字段的文本通过它们在行中的固定位置来区分(没有分隔)。

当 File1 中特定位置(例如,位置 16-20)的文本包含小于我选择的某个值(例如,小于 -5)的数值时,我希望更改相应的字段(也在第二个文件中的固定位置给出)到某个预设值(比如 10)。通过对应,我的意思是它们的行号相同(在下面的示例中 - 两者都在各自文件的第 3 行)

例如文件1:

ABC(11 个空格)5.78 3.65 9.22(更重要的东西)

EFG(11 个空格)4.78 9.65 9.99(更重要的东西)

HIJ(11 个空格)-5.78 9.99 9.99(更重要的东西)

文件 2(之前):

LMN(11 个空格)31.21 2.14 1.27(更重要的东西)

OPQ(11 个空格)4.78 9.99 9.99(更重要的东西)

RST(11 个空格)3.29 9.99 9.99(更重要的东西)

文件 2(之后):

LMN(11 个空格)31.21 2.14 1.27(更重要的东西)

OPQ(11 个空格)4.78 9.99 9.99(更重要的东西)

RST(11 个空格)10.00 9.99 9.99(更重要的东西)

对于使用脚本实用程序的某些 Unix 大师来说,这似乎应该是一项非常简单的任务,但我对这些工具还不够熟悉,无法将它们串在一起并解决任务。我只能完成其中的一部分,例如使用“cut”根据位置选择字段。例如,我在下面的 bash 脚本中做到了这一点:

#!/bin/bash
# PURPOSE: Process a file line by line with PIPED while-read loop.
FILENAME=$1
count=0
cat $FILENAME | while read LINE
do
xcoor=$(echo "$LINE" | cut -c 16-20)
let count++
if [ "$xcoor" -lt -4 ] 
then
echo "$count"
#I have identified the lines I want in the first file.  
#Now I need to modify the second file
fi
done

我的部分问题只是我一次处理 2 个文件这一事实。 最大的问题是前面提到的大量文件 - 这就是为什么我认为逐行执行它很重要 - 避免将整个文件读入内存 - 或不必要地写入临时文件。

非常感谢您提供任何帮助,如果您愿意简要说明命令的组件的作用,那将非常有帮助,因为我想了解命令的作用,以便我可以根据需要修改它们(我是 Unix 脚本的初学者。)

谢谢!

【问题讨论】:

  • better edit 你的问题给出了正确的格式,并显示了你到目前为止所尝试的内容
  • 正确格式是什么意思?示例文件具有所需的格式。
  • 对于 2 文件问题,请参阅 paste。它将两个文件中的相应行连接在一起,然后您可以像处理单个文件一样处理它们(以流方式,即无需创建临时文件)。
  • 谢谢@jas,这很有帮助。我会试试。但是,我还需要修改第二个文件。对此有何建议?
  • 是的,将 paste 的输出通过管道传输到 awk(例如)。如果 File1 中的行部分符合您的条件,则输出 File2 中行的(修改后的)部分。

标签: unix awk sed grep


【解决方案1】:

gawk 是这样的

gawk '
  BEGIN{FIELDWIDTHS="15 5 5"}      # widths of the fields - you will need to set this for your files
  FNR==NR{if($2<-5)r[NR]++;next}   # this processing only applies to file1
  FNR in r{$2="10.00"}             # this processing only applies to file2
  1' file1 file2                   # the '1' prints the record

LMN           31.21 2.14 1.27
OPQ            4.78 9.99 9.99
RST            10.00 9.99

因此,我们使用gawk 的固定宽度字段读取这两个文件。阅读第一个时,请注意数组r[] 中需要修复的所有记录。读取第二个时,修复任何需要它的记录,然后打印。

唯一保存在内存中的是所有需要修复的记录编号的列表。

我的输入文件可能与您的不同。如果需要,将输出定向到新文件,使用

gawk '...' file1 file2 > newFile

【讨论】:

  • 这非常接近我的需要,谢谢(也感谢您的描述 - 非常有帮助!)唯一的问题是,它似乎覆盖了最后一行的最后一部分,并添加了一个带有“10”的额外行:LMN(11 个空格)31.21 2.14 1.27(更重要的东西)OPQ(11 个空格)4.78 9.99 9.99(更重要的东西)RST(11 个空格)10 9.99 10
  • 您可能需要检查您的字段宽度是否与您的数据匹配,并且当您在字段 2 中输入 10 时,您实际上输入了 10.00 以匹配已删除部分的长度,如果它是5 个字符,如果是 6 个字符,则为 10.000
  • 它很接近 - 我正在考虑接受它,但由于某种原因,它覆盖了一些字符,或者增加了额外的空间。我尝试更改字段的长度,但无法正常工作。您甚至可以在示例输出中看到对齐存在一些问题,并且最后一个字段丢失。我通过添加一个条件来测试零长度字段来修复额外的行: ...FNR==NR{if($2
猜你喜欢
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多