返回列表 发帖

[文本处理] [已解决]如何使用文本工具进行整行去重、首列排序

本帖最后由 77七 于 2023-6-5 13:25 编辑

请教各位老师、大佬:
如何使用gawk或sed或grep等专业文本处理工具  对文本进行以下处理
1.按整行进行去重(如 第一行、第三行相同,则去除第三行);
2.仅对第一列进行排序(第一列相同的所有行保持原有的上下顺序)

文本 编码ansi 数万行 含有多列(空格分隔) 含有数字、汉字、符号,不含引号、叹号;
批处理 编码ansi
如 1.txt
江苏 盐城
江苏 苏州 宿迁
浙江 杭州
江苏 南京
江苏 盐城
江苏 苏州
安徽 合肥COPY
20230605 13:25 重新修改 1.txt
浙江 杭州
江苏 盐城
江苏 苏州 宿迁
江苏 南京
江苏 盐城
江苏 苏州
安徽 合肥COPY


希望几秒内处理完成,结果直接覆盖,或者得到 2.txt
2.txt
20230605 13:19 修改
utf-8编码的1.txt sort排序及手动处理结果:
江苏 盐城
江苏 苏州 宿迁
江苏 南京
江苏 苏州
浙江 杭州
安徽 合肥COPY

ansi编码的1.txt sort排序及手动处理结果:
安徽 合肥
江苏 盐城
江苏 苏州 宿迁
江苏 南京
江苏 苏州
浙江 杭州COPY

如上,排序了江苏、浙江、安徽;去除了重复行(第二个 江苏 盐城);
江苏 盐城;江苏 苏州 宿迁;江苏 南京;江苏 苏州; 的上下顺序不变。

谢谢!
补充说明:
上述2.txt结果是我错误的对utf-8编码的1.txt经过sort排序后,手动加工形成的。
像江苏、浙江、安徽的上下顺序,不影响实际使用。
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2
bat小白,请多指教!谢谢!

回复 30# aloha20200628


  谢谢老师指点!
测试排序,结果正确!
测试去重,默认带了排序功能。
如果只是简单的去重排序,代码简短容易记忆,堪称神器!
非常感谢!
bat小白,请多指教!谢谢!

TOP


看来满足LZ的特殊要求还须一个参数 -s 帮忙,订正为下式即可 》
   _sort -s -k 1,1 inF.txt>outF.txt

再分享一个有关 _sort.exe 的趣点,单用(必须是单用!)一个参数 -u 还可去重,如下式》
   _sort -u inF.txt>outF.txt

如此,去重+排序 可被 _sort.exe 一举拿下...
1

评分人数

    • 77七: 乐于助人技术 + 1

TOP

回复 28# hfxiang


   谢谢大佬!大佬的代码对首列的排序方式有点与众不同,测试排序数字,大概是按数值大小排序的;测试排序汉字,大致和批处理的sort排序相同;满足排序需求,非常感谢!
bat小白,请多指教!谢谢!

TOP

回复 17# 77七
gawk "!a[$1]++{c[++i]=$1}{b[$1,a[$1]]=$0}END{s=asort(c,tA);for(i=1;i<=s;i++)for(j=1;j<=a[tA[i]];j++)print b[tA[i],j]}" 1.txt>2.txtCOPY
1

评分人数

    • 77七: 乐于助人技术 + 1

TOP

回复 26# aloha20200628


   谢谢老师指点!我试了一下
_sort -k 1 1.txtCOPY


没有达到效果,仍然排序了第二列。
排序前
2 7
1 5
2 1
1 2
1 3
排序后
1 2
1 3
1 5
2 1
2 7
希望排序后
1 5
1 2
1 3
2 7
2 1COPY


看了sort -k的说明,我也没看明白。
-k, --key=POS1[,POS2] 在 POS1(起点 1)开始一个键,在 POS2 结束
(默认行尾)
bat小白,请多指教!谢谢!

TOP


既然LZ的主旨是要用纯P组织流程与控制,用高效第三方工具作任务执行,就用awk+sort的组合拳了。
从本站下载 sort.exe v2.1/v7.6 两个版皆可,最好更名调用(如_sort.exe)以免和系统内置款冲突。
例如》 _sort -k 1 -t ";" inF.txt>outF.txt
上式中的参数-k指定仅对第1列排序,参数-t指定各列分隔符为分号,默认是空格。

TOP

回复 24# WHY


   谢谢大佬!速度也很快,5万行文本,1-2秒左右。
bat小白,请多指教!谢谢!

TOP

本帖最后由 WHY 于 2023-6-6 09:38 编辑

bat+JS 试试
@if(0)==(0) echo off
pushd "%~dp0"
type 1.txt | cscript //nologo //e:jscript "%~f0" > 2.txt
pause & exit/b
@end
var map = {};
var num = 100000000;
var str = WSH.StdIn.ReadAll();
var arr = str.replace(
    /^(\S+)[^\r\n]*(?=\r\n|$)/mg,
    function(s0, s1){
        if (!map.hasOwnProperty(s0)){
            map[s0] = true;
            return s1 + ++num + ' ' + s0;    //每一行添加数字
        } else {
            return '';  //去重复
        }
    }
).split('\r\n').sort();
str = arr.join('\r\n').replace(/^\S+ /mg, '');     //删掉每一行添加的数字
str = str.replace(/^(?:\r\n)+/, '');               //删掉开头的回车换行
WSH.Echo(str);COPY
1

评分人数

    • 77七: 乐于助人技术 + 1

TOP

回复 22# terse

谢谢大佬!没有执着用批处理解决这个问题。这种写法学习了!测试了一下,用时12分钟。

我把代码中的去重去掉了,(因为还在set,在下午测试的时候我发现批处理set 到三四万个变量后,速度已经变得很慢 )。直接使用gawk去重,使用代码排序,耗时只需1分钟,效率已大大提高!
bat小白,请多指教!谢谢!

TOP

一定执着于批处理的话 这样处理怎么样,效率提高不大,比较SET还是否轻松点吧
@echo off&setlocal enabledelayedexpansion
REM 存为ANSI文件
%1 (for /f "tokens=1,2*" %%i in ('%0 rem ^|sort') do echo %%i %%k)>2.txt&exit
for /f "tokens=1,2*delims=: " %%a in ('findstr /n . ^< a.txt') do (
     if not defined _"%%b %%c" (
        set s=000000%%a
        echo %%b !s:~-7! %%c
     )
     set _"%%b %%c"=0
)COPY

TOP

回复 19# terse


   谢谢大佬,测试没问题,完全满足需求。批处理中的 sort 会按整行排序,排序第一列同时会排序第二列。我是想对第二列不排序,保持原有顺序。
大概是1楼,由于我的错误,和巧合,让您造成了误解,不好意思。描述起来可能比较困难,本意像13楼中我的批处理排序代码那样,第一列相同的,行号小的第二列会排在上面。
bat小白,请多指教!谢谢!

TOP

回复 18# xczxczxcz


   谢谢大佬指点!注册账号以前没接触过计算机语言,包括现在我也不知道什么是对象语言...因为现在bat基本可以满足我的实际使用需要,还有很多第三方工具可以调用补充bat的不足,所以我的想法是把bat学好就行,自己实用为主,暂时不考虑学习ps。
bat小白,请多指教!谢谢!

TOP

去重复 然后排序,只是不确定你想怎样排序,是一次性排序,还是只排关键词,试试吧,看达不到要求
gawk "{if(!c[$0]++)a[$1][b[$1]++]=$0}END{PROCINFO[\"sorted_in\"]=\"@ind_str_asc\";for(k in a)for(i=0;i<b[k];i++) print a[k][i]}" 1.txt>2.txtCOPY
回复 17# 77七
1

评分人数

    • 77七: 乐于助人技术 + 1

TOP

吐个槽:学一门对象语言,不就简单了吗,用你上面的50000行脚本,用PS排序分类也秒内完成。唉,为何总纠结bat?
QQ: 458609586
脚本优先 [PowerShell win10]

TOP

返回列表