【问题标题】:Extract data from multiple files (Structure outputs) and printing to one file从多个文件(结构输出)中提取数据并打印到一个文件
【发布时间】:2021-01-21 17:05:55
【问题描述】:

请,我需要从 400 个文件中提取值的帮助。到目前为止,我从来没有做过类似的事情,我不知道从哪里开始。由于我不是程序员,我不知道哪个软件程序会好用:R、SAS、Python、命令提示符、bash、awk。在使用命令提示符 bash 运行某些应用程序时,我在使用 SAS 和 R(主要是带有行和列的“常规”文件)进行数据操作/管理方面有一些经验。

  1. 我在云计算上运行 Structure(群体遗传学软件)。
  2. 输出为 400 个文件/运行。他们的名字是:job_01_01-output_f; job_01_02-output_f …… job_40_10-output_f
  3. 这些输出没有任何扩展名(如 .txt),但我通常使用 Textpad、Notepad++ 打开它们
  4. 在这 400 个文件/输出中的每一个中都有一行:Estimated Ln Prob of Data = -5570597.3
  5. 我想从所有这些文件/输出中提取数值 -5570597.3 并将其保存到类似 .csv、.txt 的列中(一个在另一个之下 - 类似文件的顺序相同)
  6. 此外,这一行并不总是在所有文件中的同一行,因为它取决于“参数”的数量。
  7. 所以我猜想类似“在“估计的 Ln 数据概率 =”之后取值是一种选择。
  8. 例如,一个文件/输出有大约 60000 行。这些文件的大小从 800kb 到 5mb。
  9. 例如,我将尝试上传文件/输出。

最好的问候

[LINK - 结构/文件输出示例][1]

https://www.dropbox.com/sh/idvoigkky7ldgb7/AAD5foVSKc5Ty6ijc08ge230a?dl=0

【问题讨论】:

  • 如果我正确理解了您想要的内容,那么在 终端 更改目录files 所在的位置然后使用以下复合命令awk -F'= ' '/Estimated Ln Prob of Data/{print $2}' * >> /path/to/file.csv
  • 如果你 edit 你的问题是提供一个 minimal reproducible example (没有图像和链接)简洁,可测试的文本样本输入(例如你提到的几个文本文件,每个有 4或 5 行文本)和预期输出(给定输入您想要生成的 CSV),那么会有更多人愿意/能够帮助您。见How to Ask
  • 谢谢@user3439894!这是工作!是否可以在 awk 代码中在值旁边包含文件名,以便我可以像两列一样导入此文件(空格或逗号可以是分隔符)。我忘记了这个,它会很有用。示例:job_01_01-output_f -5570597.3 job_40_01-output_f -2834943326.2
  • 是的:awk -F'= ' '/Estimated Ln Prob of Data/{print FILENAME, ",", $2}' * >> /path/to/file.csv

标签: python r bash awk cmd


【解决方案1】:

将 grep 与 PCRE 结合使用以获取来自 Dropbox 链接的正向后视和数据:

$ grep -Pohm 1 "(?<=^Estimated Ln Prob of Data   = ).*" job_*

输出:

-5570597.3
-2834943326.2

使用过的开关:

-P, --perl-regexp
          Interpret PATTERNS as Perl-compatible regular expressions (PCREs).

-h, --no-filename
          Suppress the prefixing of file names on output.

-o, --only-matching
          Print only the matched (non-empty) parts of a matching line

-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.

另一个使用 awk:

$ for f in job* ; do awk '/^Estimated Ln Prob of Data/{print $NF;exit}' $f ; done

和 GNU awk:

$ awk '/^Estimated Ln Prob of Data/{print $NF;nextfile}' job_*

【讨论】:

  • 哦,不!安息吧 Eddie Van Halen。
  • 谢谢!我尝试了 awk,它正在工作!是否可以在 awk 代码中在值旁边包含文件名,以便我可以像两列一样导入这个文件(空格或逗号可以是分隔符)。我忘记了这个,它会很有用。示例:job_01_01-output_f -5570597.3 job_40_01-output_f -2834943326.2
  • 当然,有内置变量FILENAME,只需将print $NF更改为print FILENAME, $NF即可。
【解决方案2】:

batch 你的字面问题:

(for /f "tokens=2 delims==" %%a in ('findstr /c:"Estimated Ln Prob of Data" "job_??_??-output_f"') do echo %%a)>result.csv

如果您也需要文件名:

(for /f "tokens=1,3 delims=:=" %%a in ('findstr /c:"Estimated Ln Prob of Data" "job_??_??-output_f"') do echo %%a,%%b)>result.csv

【讨论】:

    【解决方案3】:

    首先,我提供这个答案是为了提供更多选项,我认为最好的答案是James Browngrep 解决方案,因为学习精通grep 将是一项特别有用的技能。如果您认为自己可能会卡在 Windows 环境中,Stephan 的解决方案也很方便,尤其是如果您处于一个不一定有 PowerShell 的最小环境中。

    这是 PowerShell 中的一个选项:

    Get-Content "job_01_01-output_f" | ForEach-Object { if ($_ -match "Estimated Ln Prob of Data * = * ([-.\d]+)") { $Matches[1]} }
    

    还有一个使用sed的选项:

    sed -ne "s/Estimated Ln Prob of Data *= *\([-.0-9]\+\)/\1/gp" "job_01_01-output_f"
    

    【讨论】:

    • 谢谢!我也试过这段代码,它分别适用于每个文件。
    【解决方案4】:

    一个简单的 Python 实现。让我知道它是否适合你。

    import glob
    import os.path as os
    import re
    import uuid
    
    
    def extract_data(source: str,
                     export: str = None,
                     nested: bool = False,
                     delimit: str = ",",
                     extract: str = "Estimated Ln Prob of Data") -> None:
      """
      Extracts values of `Estimated Ln Prob of Data` from source and exports
      it in a text file.
      
      Args:
        source: Directory which has `job_01_01-output_f` files.
        export: Path of the output file.
        nested: Boolean, if you want to use nested files as well.
        extract: Keyword whose respective value needs to be extracted.
      """
      regex = r"^\b{}\b.+$".format(extract)
      nest = "**" if nested else "*"
      values = []
    
      for file in glob.glob(f"{source}/{nest}", recursive=True):
        raw = os.basename(file)
        if raw.startswith("job_") and raw.endswith("-output_f"):
          with open(file, "r") as _file:
            matches = re.finditer(regex, _file.read(), re.MULTILINE)
            entry = f"{raw}{delimit}{list(matches)[0].group().rsplit('= ')[-1]}\n"
            values.append(entry)
    
      export = export if export else os.join(source, f"{str(uuid.uuid4())}.txt")
      with open(export, "w") as _file:
        _file.writelines(values)
    
    
    # Where "/home/SOME_USER/Downloads" is the path where you have these 400 files.
    extract_data("/home/SOME_USER/Downloads")
    

    【讨论】:

    • 谢谢!在职的!是否可以在值旁边包含文件名,以便我可以像两列一样导入这个文件(空格或逗号可以是分隔符)。示例:job_01_01-output_f -5570597.3 job_40_01-output_f -2834943326.2
    • 完成,添加了对分隔符的支持(默认为逗号 ",")@Bella
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多