Board logo

标题: [问题求助] PowerShell对比两个CSV文件后, 在重复的项后面,加一列 [打印本页]

作者: 5i365    时间: 2022-1-19 23:50     标题: PowerShell对比两个CSV文件后, 在重复的项后面,加一列

对比两个CSV文件后, 在重复的项后面,加一列, 具体描述如下:

A.csv 文件内容:

排序,语言,歌手,歌名
1,国语,付雪,金玉良缘
2,国语,阿吉太组合,阿衣莫
3,国语,洛先生,孤城
4,国语,刘艺雯,听闻远方有你
5,国语,海来阿木,五十年以后
6,国语,海来阿木,浮生记
7,国语,杨小壮,最后的人
8,国语,莫叫姐姐,你能不能不要离开我 (莫叫语版)
9,国语,郁可唯,路过人间
10,国语,乔佳旭,雪下的时候

B.csv 文件内容:

排序,语言,歌手,歌名
1,国语,付雪,金玉良缘
2,国语,阿吉太组合,阿衣莫
3,国语,洛先生,孤城
5,国语,海来阿木,五十年以后
6,国语,海来阿木,浮生记
--------------------------------------------------------------------------------------------------
期待结果,在A中的如果有与B中重复的项,则在后面添加  已完成  列, 如下:

排序,语言,歌手,歌名
1,国语,付雪,金玉良缘,已完成
2,国语,阿吉太组合,阿衣莫,已完成
3,国语,洛先生,孤城,已完成
4,国语,刘艺雯,听闻远方有你
5,国语,海来阿木,五十年以后,已完成
6,国语,海来阿木,浮生记,已完成
7,国语,杨小壮,最后的人
8,国语,莫叫姐姐,你能不能不要离开我 (莫叫语版)
9,国语,郁可唯,路过人间
10,国语,乔佳旭,雪下的时候
作者: qixiaobin0715    时间: 2022-1-20 07:04

本帖最后由 qixiaobin0715 于 2022-1-20 09:31 编辑

用批处理试试。
正常代码:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "skip=1 tokens=1* delims=," %%a in (b.csv) do set "%%b=true"
  4. (for /f "tokens=1* delims=," %%i in (a.csv) do (
  5.     if defined %%j (
  6.         echo,%%i,%%j,已完成
  7.     ) else (
  8.         echo,%%i,%%j
  9.     )
  10. ))>c.csv
  11. move c.csv a.csv
  12. pause
复制代码
合并成一行:
  1. @setlocal enabledelayedexpansion&(for /f "skip=1 tokens=1* delims=," %%a in (b.csv) do set "%%b=true")&(for /f "tokens=1* delims=," %%i in (a.csv) do (if defined %%j (echo,%%i,%%j,已完成) else echo,%%i,%%j))>c.csv&move c.csv a.csv
复制代码

作者: 5i365    时间: 2022-1-20 08:33

本帖最后由 5i365 于 2022-1-20 08:37 编辑

回复 2# qixiaobin0715


    非常感谢,

又遇到糟心的乱码问题了!
A.csv和b.csv必须全部是ANSI编码, 编码不同, 或编码都是UTF8, 生成的会是乱码, 这个有什么万能的解法吗?
另外,发现UTF8编码的CSV文件用Excel打开时会乱码, 还要转成ANSI,
作者: 5i365    时间: 2022-1-20 08:43

回复 2# qixiaobin0715


    刚试了下单行的那个批处理, 生成的文件全是如下类似的路径, 修改单行CMD,像是雾里看花, 看来最好还是用powershell代码
C:\Users\Administrator\Desktop\新建文件夹>(if defined 国语,洛先生,孤城 (echo,3,国语,洛先生,孤城,已完成 )  else echo,3,国语,洛先生,孤城 )
作者: 5i365    时间: 2022-1-20 08:50

我现在能想到的万能的解法是, 不管原文本文件是什么编码格式, 都先用@went大侠的 Coder转成utf8, 然后用powershell代码 导入和导出文本文件
作者: 5i365    时间: 2022-1-20 09:01

回复 2# qixiaobin0715


    我现在不明白, 为什么A.csv和B.csv文件都是UTF8的情况下会产生乱码, UTF8不是兼容所有字符吗?
作者: qixiaobin0715    时间: 2022-1-20 09:33

回复 4# 5i365
忘记关闭回显(代码前加@)了。已修改。
作者: qixiaobin0715    时间: 2022-1-20 09:36

看到前辈们处理UTF8是在前面加chcp 65001>nul。
作者: qixiaobin0715    时间: 2022-1-20 09:44

只是以前看到你想把cmd写成一行,自己也想练练手,瞎写的。
作者: 5i365    时间: 2022-1-20 09:50

回复 9# qixiaobin0715


    感谢, 你懂我!
作者: 5i365    时间: 2022-1-20 09:52

回复 7# qixiaobin0715


    加关闭回显也不行, 我尝试加了@echo off& 也一样的
作者: 5i365    时间: 2022-1-20 10:01

本帖最后由 5i365 于 2022-1-20 10:13 编辑

回复 9# qixiaobin0715


    我把A和B都改成了utf8 ,然后执行下面的代码:
@echo off
chcp 65001>nul
setlocal enabledelayedexpansion
for /f "skip=1 tokens=1* delims=," %%a in (b.csv) do set "%%b=true"
(for /f "tokens=1* delims=," %%i in (a.csv) do (
    if defined %%j (
        echo,%%i,%%j,已完成
    ) else (
        echo,%%i,%%j
    )
))>c.csv
REM move c.csv a.csv
pause
----------------------------------------------------------------
得到的结果:
排序,语言,歌手,歌名
1,国语,付雪,金玉良缘,�����
2,国语,阿吉太组合,阿衣莫,�����
3,国语,洛先生,孤城,�����
4,国语,刘艺雯,听闻远方有你
5,国语,海来阿木,五十年以后,�����
6,国语,海来阿木,浮生记,�����
7,国语,杨小壮,最后的人
8,国语,莫叫姐姐,你能不能不要离开我 (莫叫语版)
9,国语,郁可唯,路过人间
10,国语,乔佳旭,雪下的时候
作者: qixiaobin0715    时间: 2022-1-20 10:39

本帖最后由 qixiaobin0715 于 2022-1-20 10:44 编辑

回复 12# 5i365
  1. @echo off &@cls&chcp>nul 65001
  2. @setlocal enabledelayedexpansion&(for /f "skip=1 tokens=1* delims=," %%a in (b.csv) do set "%%b=true")&(for /f "tokens=1* delims=," %%i in (a.csv) do (if defined %%j (echo,%%i,%%j,已完成) else echo,%%i,%%j))>c.csv&move c.csv a.csv
复制代码
bat文件编码也要改。
作者: for_flr    时间: 2022-1-20 11:05

  1. gc b.csv|?{(gc a.csv) -contains $_}|%{$_ -replace "^\d.*","$_,已完成"}
复制代码

作者: 5i365    时间: 2022-1-20 11:14

回复 14# for_flr


    回显如下, 只有上半部分, 不加 已完成的也需要显示:
排序,语言,歌手,歌名
1,国语,付雪,金玉良缘,已完成
2,国语,阿吉太组合,阿衣莫,已完成
3,国语,洛先生,孤城,已完成
5,国语,海来阿木,五十年以后,已完成
6,国语,海来阿木,浮生记,已完成
作者: for_flr    时间: 2022-1-20 11:32

回复 15# 5i365
  1.   gc a.csv|%{if((gc b.csv) -match "^\d" -contains $_){"$_,已完成"}else{$_}}
复制代码

作者: 5i365    时间: 2022-1-20 11:43

回复 16# for_flr


    我的a.csv 有3000行, b有200行, 执行时间有点长, 有能快点的方法吗? 批处理执行的很快
作者: for_flr    时间: 2022-1-20 11:49

有,gc a.csv -readcount 0
|%{}处理改作for循环
你可以琢磨一下,我下班放假了 :lol
作者: 5i365    时间: 2022-1-20 12:05

回复 18# for_flr


    感谢提醒,

不太懂foreach和for在这里怎么转换, 有路过的大侠, 帮试一下
作者: idwma    时间: 2022-1-20 15:36

还可以试试哈希表的方式
  1. $f=gc a.csv
  2. $a=@{}
  3. $rex={[int]($_ -replace '^(\d+),.*','$1')}
  4. $f[1..$f.count]|%{$a+=@{$(&$rex)=$_}}
  5. (gc b.csv)[1..$f.count]|%{if($a.contains($(&$rex))){$a[$(&$rex)]=$a[$(&$rex)]+',已完成'}}
  6. sc c.csv ($f[0],$(do{$a[++$bcc]}while($a[$bcc] -ne $null)))
复制代码

作者: 5i365    时间: 2022-1-20 18:19

回复 20# idwma


    牛X 这个执行速度快多了, 为什么?
作者: idwma    时间: 2022-1-20 19:44

回复 21# 5i365


    减少了循环次数




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2