【问题标题】:lightest way to join 2 CSV (like an SQL LEFT JOIN)加入 2 个 CSV 的最简单方法(如 SQL LEFT JOIN)
【发布时间】:2021-10-01 03:51:17
【问题描述】:

我依靠社区专业知识来指导我以最佳方式了解以下主题。

在无法安装 MS-Office 应用程序的 Windows 上运行的专业环境中,我需要向我的团队分发一种方法来加入 2 个 CSV 文件并生成第 3 个 CSV 文件作为输出。就像我们运行 SQL 查询一样:

SELECT f1.*, f1.bar = f2.bar as baz 
FROM CSVfile1 as f1 
LEFT JOIN CSVfile2 as f2 
ON f1.key = f2.key

目前使用 Excel + VBA 已达到目标,但 MS-office 软件包将被删除且不再可访问。出于同样的原因,无法设想使用 MS-Acces 的解决方案。

目标是允许任何机构在没有任何能力和特定安装的情况下实现第三个 CSV 计算机。所以使用 python 或 MS-SQL-Servr 的方法也不好。

我想用 Powshell 脚本来实现,但首先。我没有使用 PowerShell 的习惯,但我可以学习。

但在尝试之前,我向社区询问这是否是最好的方法?或者如果有更好的解决方案? (要求:Windows 操作系统(最新版本),无 MS-office,无特定安装)。

谢谢大家。

【问题讨论】:

  • 如果文件很大......使用类似 sqlite 的东西并在那里完成工作。 ///// PSGallery 网站上有几个“加入 csv”脚本。他们似乎工作得很好。 ///// 或者,您可能想要查看 hashset 类。 HashSet 类 (System.Collections.Generic) | Microsoft Docs — docs.microsoft.com/en-us/dotnet/api/… ///// 有几篇关于如何在网络上的 PoSh 中使用它的帖子。 [咧嘴]
  • 忽略“无特定安装”也许模块“ImportExcel”可以帮助解决powershellgallery.com/packages/ImportExcel/7.1.2(与它的名称相反的作用不仅仅是导入)
  • 请为我写代码是一个询问,而不是一个可以回答的问题。 Stack Overflow 是针对后者的。
  • 提问者问这是否是最好的方法。这不是要代码。
  • 正是沃尔特·米蒂。我熟悉通过 VBA 进行处理,但最近公司正在删除 MS 许可证。我很确定我可以用 python 处理我的 CSV,如果它是用于我自己的机器的,但我不想要求超过 100 人在他们的计算机上安装 python。我只是在寻找哪种方法允许我对处理进行编码,而其他方法可以启动它,即使他们不知道并且现在安装了特定的软件。

标签: windows powershell csv left-join


【解决方案1】:

PowerShell 在 v7.2 中没有内置的连接功能(类似于 SQL 的[1]),尽管在GitHub issue #14994;可通过PowerShell Gallery(例如JoinModule)获得第三方解决方案

目前,如果无法选择安装第三方工具,您可以推出自己的解决方案,使用以下方法,使用Import-Csv 加载 CSV 文件,辅助@ 987654325@ 查找对应的行,Add-Member 添加列(属性)。

# Create sample CSV files.
$csv2 = @'
key,bar,quux
key1,bar1,quux1
key2,bar2,quux2
key3,bar3,quux3
'@ > ./CSVFile1.csv

@'
key,bar
key1,bar1
key2,bar2a
'@ > ./CSVFile2.csv

# Import the the 2nd file and load its rows 
# (as objects with properties reflecting the columns)
# into a hashtable, keyed by the column 'key' values.
$hash = @{}
foreach ($row in Import-Csv ./CSVFile2.csv) {
  $hash[$row.key] = $row
}

# Import the 1st file and process each row (object):
# Look for a matching object from the 2nd file and add 
# a calculated column derived from both objects to the
# input object.
Import-Csv ./CSVFile1.csv | ForEach-Object {
  $matching = $hash[$_.key]
  $_ |
    Add-Member -PassThru baz $(if ($matching) { [int] ($matching.bar -eq $_.bar) })
}

将最后一条语句通过管道传递到 Export-Csv 以将生成的对象导出到 CSV 文件。 (例如
... | Export-Csv -NoTypeInformation -Encoding utf8 Results.csv

以上结果如下:

key  bar  quux  baz
---  ---  ----  ---
key1 bar1 quux1   1
key2 bar2 quux2   0
key3 bar3 quux3    

[1] 有一个-join operator,但它的目的是将一个单个数组的元素连接起来形成一个单个字符串。支持>

【讨论】:

    【解决方案2】:

    这是使用 sqlite 命令行 shell(单个 900kb 可执行文件)和相同的 sql join 命令的现成答案。 https://sqlite.org/download.html Sqlite 似乎在处理 utf16 或“unicode”文本文件时遇到了问题。即使是 Excel 在导入 utf16 csv 时也比较麻烦。

    # making csv file with ">" (utf16) caused this error:
    # CREATE TABLE csvfile1(...) failed: duplicate column name:
    
    'key,bar,quux
    key1,bar1,quux1
    key2,bar2,quux2
    key3,bar3,quux3' | set-content csvfile1.csv
    
    'key,bar
    key1,bar1
    key2,bar2a' | set-content csvfile2.csv
    
    '.mode csv
    .import csvfile1.csv csvfile1
    .import csvfile2.csv csvfile2
    .headers on
    SELECT f1.*, f1.bar = f2.bar as baz 
    FROM CSVfile1 as f1 
    LEFT JOIN CSVfile2 as f2 
    ON f1.key = f2.key' | .\sqlite3
    
    # output
    
    # key,bar,quux,baz
    # key1,bar1,quux1,1
    # key2,bar2,quux2,0
    # key3,bar3,quux3,
    
    

    【讨论】:

    • 不是根据问题要求的选项(“无特定安装”),但对简单的SQLite 解决方案表示敬意。
    • 你让我重新考虑我的要求。我将研究如何实施 SQlite 解决方案与 PoSh 解决方案。也许我的团队可以通过良好的指导轻松使用 SQlite。 (我想他们必须先安装 SQlite,我需要解释这样做的好处)。
    • 如果你喜欢图形界面,还有 sqlite studio。
    猜你喜欢
    • 2010-11-22
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 2016-04-12
    • 2014-08-10
    相关资源
    最近更新 更多