Board logo

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

作者: 思想之翼    时间: 2023-11-12 04:54     标题: 【已解决】gawk:如何提取指定个数的字符

本帖最后由 思想之翼 于 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,结果为空
作者: Five66    时间: 2023-11-12 07:08

这样可以不?
将代码保存为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. }
复制代码

作者: 思想之翼    时间: 2023-11-12 07:36

本帖最后由 思想之翼 于 2023-11-12 08:11 编辑

回复 2# Five66

感谢!
假如确定N=10(不用在运行界面输入),结果输出为文本B.txt,上述gawk代码如何简化?
作者: qixiaobin0715    时间: 2023-11-12 09:12

练练手,用纯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
复制代码

作者: wanghan519    时间: 2023-11-12 09:27

不知道行不
  1. awk -v RS='\r?\n| ' -v ORS=' ' '{++d[$0]}END{for(i in d){if(d[i]==1){print i}}}' a.txt
复制代码

作者: czjt1234    时间: 2023-11-12 09:31

纯P好象不行,楼主的文件好象都是很大的
作者: qixiaobin0715    时间: 2023-11-12 09:53

本帖最后由 qixiaobin0715 于 2023-11-12 09:56 编辑

回复 6# czjt1234
这与文件大小关系不大,只与相异字符总量有关,如果相异字符超过一定数量,可能会有问题。并且楼主在顶楼说的是“字母”,也就是26个而已,这样代码就不会设置更多变量。
作者: aloha20200628    时间: 2023-11-12 10:54

本帖最后由 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();
复制代码

作者: hfxiang    时间: 2023-11-12 14:23

回复 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"
复制代码

作者: 思想之翼    时间: 2023-11-12 19:54

本帖最后由 思想之翼 于 2023-11-12 20:00 编辑

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

回复 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"
复制代码





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