【问题标题】:unix delete rows from multiple files using input from another fileunix 使用来自另一个文件的输入从多个文件中删除行
【发布时间】:2014-06-04 13:01:53
【问题描述】:

我有多个 (1086) 文件 (.dat),在每个文件中我有 5 列和 6384 行。 我有一个名为“info.txt”的文件,其中包含 2 列和 6883 行。第一列给出行号(在 .dat 文件中删除),第二列给出一个数字。

1 600
2 100
3 210
4 1200

等等... 我需要阅读 info.txt,在第二列中找到与小于 300 的值对应的每一行号(因此在上面的示例中为 2 和 3)。然后我需要将这些值读入 sed-awk 或 grep 并从每个 .dat 文件中删除这些 #lines。 (所以我会在上面的例子中删除每2行和3行dat文件)。

问题的更一般形式是(我想): 如何从文件中读取数字作为输入,而不是将它们分配给要从多个文件中删除的行。

我正在使用 bash,但 ksh 帮助也很好。

【问题讨论】:

  • 请提供一个更简单的示例,显示输入文件和您想要的输出。
  • 在您的示例中,只有第一行在第二列中的值大于 300,所以在我看来,您只会从数据文件中删除第 1 行,而不是第 2 行和3.
  • 对不起,应该是小于 300 的值。
  • 你能编辑它并清理它吗?此外,在您的第二句话中,您说“2 行和 6883 行”。我假设您实际上是指“2 列和 6883 行”。

标签: bash unix awk sed grep


【解决方案1】:
sed -i "$(awk '$2 < 300 { print $1 "d" }' info.txt)" *.dat

Awk 脚本创建一个简单的sed 脚本来删除选定的行;它在所有 *.dat 文件上运行的脚本。

(如果您的sed 缺少-i 选项,您将需要在循环中写入临时文件。在OSX 和某些*BSD 上您需要-i "" 和一个空参数。)

【讨论】:

  • 我认为这有问题,但我不确定。 sed 删除第 1 行后,第 2 行不就是第 1 行了吗?那么,如果你删除第 2 行,你现在不是删除第 3 行吗?我认为您必须对行号进行反向排序才能删除某处。
  • 另外,你需要保证唯一性。如果你删除了第 25 行,你就不想再删除第 25 行了。
  • 你为什么这么认为?你试过了吗? sed 指的是原始输入文件中的行号。
  • 显然,我没有尝试,这就是为什么我说“我不确定”。但是如果它总是引用原始文件,那么应该没有问题。
  • 好吧,澄清它是否有效:这很好!对此,我真的非常感激 !非常感谢三人组!
【解决方案2】:

这可能对你有用(GNU sed):

sed -rn 's/^(\S+)\s*([1-9]|[1-9][0-9]|[12][0-9][0-9])$/\1d/p' info.txt | 
sed -i -f - *.dat

这会构建一个脚本,其中包含要从 info.txt 文件中删除的行,然后将其应用于 .dat 文件。

注意根据 OP 请求,正则表达式适用于 1 到 299 之间的数字。

【讨论】:

    【解决方案3】:
    # create action list
    cat info.txt | while read LineRef Index
     do
       if [ ${Index} -lt 300 ]
        then
          ActionReq="${ActionReq};${Index} b
    "
        fi
     done
    
    # apply action on files
    for EachFile in ( YourListSelectionOf.dat )
     do
       sed -i -n -e "${ActionReq}
    p" ${EachFile}
     done
    

    (未测试,这里没有 linux)。 sed 限制您对 seconf 值大于 300 的行的请求。awk 在此操作中更有效。 我在第二个循环中使用 sed 来避免为要删除的每一行读取/写入每个文件。我认为可以通过将文件列表直接提供给 sed 来代替文件来避免第二个循环

    【讨论】:

    【解决方案4】:

    这应该使用 oldname_new.dat 创建一个新的 dat 文件,但我还没有测试:

    awk 'FNR==NR{if($2<300)a[$1]=$1;next}
         !(FNR in a)
         {print >FILENAME"_new.dat"}' info.txt *.dat
    

    【讨论】:

      猜你喜欢
      • 2011-06-14
      • 2014-11-30
      • 2017-07-15
      • 2018-02-24
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 1970-01-01
      • 2013-06-01
      相关资源
      最近更新 更多