找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 22659|回复: 10

[文本处理] 【已解决】gawk:如何提取指定个数的字符

[复制链接]
发表于 2023-11-12 04:54:28 | 显示全部楼层 |阅读模式
本帖最后由 思想之翼 于 2023-11-12 20:46 编辑

D:\JZ\A.txt  每行记录若干字母,格式如下:
G B B
B C C C A
J A
J
E
E D

【问题】如何用gawk,提取A.txt出现N次的字符?
若指定个数的字符不存在,则输出文本为空。
上例N=2,结果为J A E
上例N=3,结果为B C
上例N=4,结果为空

评分

参与人数 1PB +2 收起 理由
Batcher + 2 感谢给帖子标题标注[已解决]字样

查看全部评分

发表于 2023-11-12 07:08:05 | 显示全部楼层
这样可以不?
将代码保存为ANSI编码的bat,放在A.txt所在目录下运行,另外需要A.txt的编码为gbk,还有注意同次数的字符过多可能出错,循环65536次后会退出

也可以直接在命令行窗口输入
gawk -f 代码文件名 文本文件名
来查看所有的次数结果

  1. # 2>nul&cls&@echo off&set "file=A.txt"
  2. # 2>nul&for /f "tokens=1* delims= " %%a in ('gawk -f "%~f0" "%file%"') do set _%%a=%%b
  3. # 2>nul&setlocal enabledelayedexpansion
  4. # 2>nul&for /l %%a in (0,1,65535) do (echo,&set /p n=请输入N的值  N=&echo,&for %%a in ("!n!") do echo,!_%%~a!)
  5. # 2>nul&endlocal&pause&exit/b

  6. BEGIN{
  7. FS=" "
  8. while((getline <ARGV[1])>0){
  9. for(i=1;i<=NF;i++)
  10. A[$i]++
  11. }
  12. for(i in A){
  13. B[A[i]]=B[A[i]]?B[A[i]]" "i:i
  14. }
  15. for(i in B)print i,B[i]
  16. }
复制代码

评分

参与人数 1技术 +1 收起 理由
思想之翼 + 1 感谢分享

查看全部评分

 楼主| 发表于 2023-11-12 07:36:22 | 显示全部楼层
本帖最后由 思想之翼 于 2023-11-12 08:11 编辑

回复 2# Five66

感谢!
假如确定N=10(不用在运行界面输入),结果输出为文本B.txt,上述gawk代码如何简化?
发表于 2023-11-12 09:12:14 | 显示全部楼层
练练手,用纯P试试:
  1. @echo off
  2. cd "D:\JZ"
  3. set N=10
  4. setlocal enabledelayedexpansion
  5. for /f "delims=" %%i in (a.txt) do (
  6.     for %%j in (%%i) do (
  7.         set /a _%%j+=1
  8.         if !_%%j! equ !N! (
  9.             set #%%j=true
  10.         ) else (
  11.             if !_%%j! gtr !N! set #%%j=
  12.         )
  13.     )
  14. )
  15. for /f "delims=#=" %%k in ('set #') do set str=!str! %%k
  16. if defined str echo,!str:~1!>b.txt
复制代码

评分

参与人数 1技术 +1 收起 理由
思想之翼 + 1 感谢分享

查看全部评分

发表于 2023-11-12 09:27:10 | 显示全部楼层
不知道行不
  1. awk -v RS='\r?\n| ' -v ORS=' ' '{++d[$0]}END{for(i in d){if(d[i]==1){print i}}}' a.txt
复制代码

评分

参与人数 2技术 +2 收起 理由
buyiyang + 1 简洁有力
思想之翼 + 1 感谢分享

查看全部评分

发表于 2023-11-12 09:31:24 | 显示全部楼层
纯P好象不行,楼主的文件好象都是很大的
发表于 2023-11-12 09:53:35 | 显示全部楼层
本帖最后由 qixiaobin0715 于 2023-11-12 09:56 编辑

回复 6# czjt1234
这与文件大小关系不大,只与相异字符总量有关,如果相异字符超过一定数量,可能会有问题。并且楼主在顶楼说的是“字母”,也就是26个而已,这样代码就不会设置更多变量。
发表于 2023-11-12 10:54:37 | 显示全部楼层
本帖最后由 aloha20200628 于 2023-11-12 13:01 编辑


纯P求解字符重复数量的方案,还是采用变量名字典最为简捷,但有原生限制,例如不区分变量名字母大小写,例如文件每行字节长度受限8K。
针对一楼示例,每行均为大写字母且用系统默认分隔符,求其各字符的重复数量,代码如下》

  1. @echo off &setlocal enabledelayedexpansion
  2. for /f "delims=" %%s in (a.txt) do for %%c in (%%s) do if defined 【%%c】 (set/a "【%%c】+=1") else (set "【%%c】=1")
  3. set 【
  4. endlocal &exit/b
复制代码
类似变量名字典的纯P算法,再用jscript+cmd混编一个(存为*.cmd批处理脚本文件运行),可区分被统计字符的字母大小写。

  1. @set @v=1 /*
  2. @echo off
  3. cscript /e:jscript "%~f0" "a.txt" |sort
  4. pause &exit/b
  5. */
  6. var fso=new ActiveXObject('scripting.filesystemobject');
  7. var fr=fso.opentextfile(WSH.arguments(0)), lines=fr.readall().split('\r\n'); fr.close();
  8. var ln=lines.length, dc={};
  9. for (var k=0; k<ln; ++k) {
  10.         var a=lines[k].split(''), an=a.length;
  11.         for (var n=0; n<an; ++n) if (dc[a[n]]==undefined) dc[a[n]]=1; else dc[a[n]]++;
  12. }
  13. for (var key in dc) WSH.echo('字符: ' + key + ' 重复次数=' + dc[key]);
  14. WSH.quit();
复制代码

评分

参与人数 2技术 +2 收起 理由
buyiyang + 1 感谢分享!第十行应该是以空格分隔
思想之翼 + 1 感谢分享

查看全部评分

发表于 2023-11-12 14:23:58 | 显示全部楼层
回复 1# 思想之翼

  1. gawk -v"N=2" -v"FS=" "{for(i=1;i<=NF;i++)if($i~/[A-Za-z]/)a[$i]++}END{for(i in a)if(a[i]==N)printf i" ";ptint""}" "D:\JZ\A.txt">"D:\JZ\B.txt"
复制代码

评分

参与人数 1技术 +1 收起 理由
思想之翼 + 1 感谢分享

查看全部评分

 楼主| 发表于 2023-11-12 19:54:43 | 显示全部楼层
本帖最后由 思想之翼 于 2023-11-12 20:00 编辑

回复 9# hfxiang
感谢!
文本是字母,正则表达式为 [A-Za-z]
文本是数值(例如:000 001...999,或00 01...99,或0 1...9),或者单个汉字(例如:挥 斥 方 遒 书 生 意 气),或者为词组(例如:挥斥方遒 书生意气),皆以空格间隔,正则表达式如何表达?
发表于 2023-11-12 20:15:55 | 显示全部楼层
回复 10# 思想之翼

如果都以空格分隔,则无须考虑正则表达式,参照5楼的指令即可:

  1. gawk -v"N=2" -v"RS=\r?\n| " -v"ORS= " "{++d[$0]}END{for(i in d)if(d[i]==N)print i}" "D:\JZ\A.txt">"D:\JZ\B.txt"
复制代码

评分

参与人数 1技术 +1 收起 理由
思想之翼 + 1 感谢分享

查看全部评分

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-18 07:45 , Processed in 0.022660 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表