无忧启动论坛

标题: 命令如何查找有中文字符的行 [打印本页]

作者: yjqd    时间: 2022-5-19 07:38
标题: 命令如何查找有中文字符的行


命令如何查找有中文字符的行

test.txt内容如下:

Meng said the commission will step
one 129 ok
two78kl
three99 88 ui
thre99 88 ui6
bk高兴oewp
89爵士io
12听99

作者: dos时代菜鸟    时间: 2022-5-19 09:18
本帖最后由 dos时代菜鸟 于 2022-5-19 12:26 编辑
  1. @echo off
  2. setlocal ENABLEDELAYEDEXPANSION
  3. set file1=test.txt
  4. set "string1=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890~!@#$*()_+`-=,.?/;"'{}[]\^|^<^>^&%%^^^^ "
  5. for /f "delims=" %%c in ('type !file1!') do (
  6.     call :str_x "%%c"
  7.     if !found0! EQU 1 ECHO "%%c"  
  8. )

  9. pause
  10. goto :eof

  11. :str_x
  12.     set "str1=%~1"
  13.     SET found0=0
  14.     for /l %%i in (0,1,255) do (
  15.         set ch=!str1:~%%i,1!
  16.         if not "!ch!"=="" (
  17.             set found1=0
  18.             for /l %%n in (0,1,92) do (
  19.                 if "!ch!"=="!string1:~%%n,1!" set /a found1 +=1
  20.             )
  21.             if !found1! EQU 0 (
  22.                 set found0=1
  23.                 exit /b
  24.             )
  25.         ) else (exit /b)
  26.     )
  27. exit /b
复制代码



先做个字典包含 键盘常规字符,然后 ,读取文件每一行,逐行逐字符判断,如果该字符不在 字典中,就判定为 中文。假定 文件每行最多 256个字符。



作者: yjqd    时间: 2022-5-19 09:25
dos时代菜鸟 发表于 2022-5-19 09:18
先做个字典包含 键盘常规字符,然后 ,读取文件每一行,逐行逐字符判断,如果该字符不在 字典中,就 ...

谢谢!

我用findstr 的下面的参数都很难实现查找有中文字符的行
[class]
[^class]
[x-y]
作者: dos时代菜鸟    时间: 2022-5-19 11:29
这个 ^ 太麻烦。
作者: nttwqz    时间: 2022-5-19 11:41
本帖最后由 nttwqz 于 2022-5-19 22:45 编辑

python 3.10.4,简单试了一下,可用。

20220519
更新下,增加chardet检测文件编码,简单测试下,常见的ANSI、UTF-8、Unicode识别正常,其它编码未知。

  1. # -*- coding: utf-8 -*-
  2. # Python 3.10.4
  3. # chardet是第三方库,需要在cmd中输入pip install chardet手动安装

  4. import os, re
  5. from chardet.universaldetector import UniversalDetector
  6. from tkinter import filedialog

  7. with filedialog.askopenfile(filetypes=[('文本文件', ['*.txt', '*.log']), ('所有文件', '*.*')]) as f:
  8.     txtfile = f.name
  9.     fname, fext = os.path.splitext(f.name)

  10. # 使用 chardet 库判断文件编码
  11. with open(txtfile, 'rb') as f:
  12.     u = UniversalDetector()
  13.     for i in f:
  14.         u.feed(i)
  15.         if u.done:      # 当识别出编码后,done的值为True,否则为False
  16.             u.close()
  17.             current_encoding = u.result['encoding']
  18.             break
  19.     if not u.done:
  20.         current_encoding = input('无法识别文件编码,请手动输入:')

  21. with open(txtfile, mode='r', encoding=current_encoding) as f:
  22.     print('查找文件 {} 中所有含中文的行\n'.format(os.path.abspath(f.name)))
  23.     sclines = ''
  24.     for line in f:
  25.         if re.search(r'[\u4e00-\u9fff]', line):
  26.             sclines += line

  27. # 生成含中文行的新文件,文件编码与源文件保持不变
  28. if sclines != '':
  29.     with open('{}_含中文的行{}'.format(fname, fext), mode='w', encoding=current_encoding) as f:
  30.         f.write(sclines)
  31.         print('含中文的行已写入到新文件:\n{}\n\n'.format(os.path.abspath(f.name)))
  32. else:
  33.     print('该文件不含中文!\n')

  34. os.system('pause')
复制代码

作者: szwp    时间: 2022-5-19 12:13
findstr /r /c:"[^- '!-Z]" text.txt
作者: yjqd    时间: 2022-5-19 20:17
szwp 发表于 2022-5-19 12:13
findstr /r /c:"[^- '!-Z]" text.txt

查找效率确实高,原版boot.wim镜像的文件列表中,随意加入一些中文,几乎秒查出带中文的行

命令行中的"Z",不能换成小写的"z",否则,凡是有大写Z的行也要被查找出来,这是什么原因?
作者: nttwqz    时间: 2022-5-19 20:26
szwp 发表于 2022-5-19 12:13
findstr /r /c:"[^- '!-Z]" text.txt

还有高手!

请教下^- '!-Z的含义?我只是个卖唱的,只知道0-9a-z的含义。。。
作者: szwp    时间: 2022-5-20 08:06
yjqd 发表于 2022-5-19 20:17
查找效率确实高,原版boot.wim镜像的文件列表中,随意加入一些中文,几乎秒查出带中文的行

命令行中的 ...

如果是文件列表,则范围可以更小了,有不少字符是不能作文件名的。
不知道你要Z还是z,将需求说得更明确些好。这个是用了[^class],当然[class]也可实现。
作者: szwp    时间: 2022-5-20 08:08
nttwqz 发表于 2022-5-19 20:26
还有高手!

请教下^- '!-Z的含义?我只是个卖唱的,只知道0-9a-z的含义。。。

当时正好要午睡了zzz,只是随便百度的的,正则费脑的,多想容易睡不着。
作者: yjqd    时间: 2022-5-20 08:46
szwp 发表于 2022-5-20 08:06
如果是文件列表,则范围可以更小了,有不少字符是不能作文件名的。
不知道你要Z还是z,将需求说得更明确 ...

谢谢!

我是需要在文本中只查找带有中文字符的行

我昨天测试的时候,把Z写成z了,结果是没有中文字符的行但有大写的的Z的行也被查找出来了
作者: szwp    时间: 2022-5-20 09:03
yjqd 发表于 2022-5-20 08:46
谢谢!

我是需要在文本中只查找带有中文字符的行

俺喜欢复制粘贴,省事啊。
作者: szwp    时间: 2022-5-20 09:09
nttwqz 发表于 2022-5-19 20:26
还有高手!

请教下^- '!-Z的含义?我只是个卖唱的,只知道0-9a-z的含义。。。

就一楼给的测试数据,用 findstr /r /c:"[^ a-z0-9]" text.txt 就可以了,这样是不是更容易理解些?
作者: yjqd    时间: 2022-5-20 09:25
szwp 发表于 2022-5-20 09:09
就一楼给的测试数据,用 findstr /r /c:"[^ a-z0-9]" text.txt 就可以了,这样是不是更容易理解些?

谢谢!

这个相对容易理解了,我昨天也写过这样的命令,但^和a-z0-9之间没空一格,导致所有行查出来了
^后空一格是什么意思

另外,你昨天的命令是不是更适合任何内容的文本,不一定是文件列表的文本,比如dism的log日志

作者: szwp    时间: 2022-5-20 09:41
yjqd 发表于 2022-5-20 09:25
谢谢!

这个相对容易理解了,我昨天也写过这样的命令,但^和a-z0-9之间没空一格,导致所有行查出来了
...

你要什么东西,就提供原始和结果的附件。正则是有书的,需要时间去掌握。
作者: yjqd    时间: 2022-5-20 09:53
szwp 发表于 2022-5-20 09:41
你要什么东西,就提供原始和结果的附件。正则是有书的,需要时间去掌握。

谢谢,不好意思,麻烦了
关于字符集里字母的大小写也影响结果
test.txt:
Meng said the commission will step
one 129 ok
two78kl
three99 88 ui
thre99 88 ui6
中有粉因
bk高兴oewp
89爵士io
12听99
jkloppDZ
E:\win10pe10586制作\新建文件夹>findstr /r /c:"[^ A-z0-9]" test.txt
Meng said the commission will step
中有粉因
bk高兴oewp
89爵士io
12听99
jkloppDZ
E:\win10pe10586制作\新建文件夹>findstr /r /c:"[^ a-Z0-9]" test.txt
中有粉因
bk高兴oewp
89爵士io
12听99

E:\win10pe10586制作\新建文件夹>findstr /r /c:"[^ A-Z0-9]" test.txt
Meng said the commission will step
中有粉因
bk高兴oewp
89爵士io
12听99


E:\win10pe10586制作\新建文件夹>findstr /r /c:"[^ a-z0-9]" test.txt
中有粉因
bk高兴oewp
89爵士io
12听99
jkloppDZ


作者: szwp    时间: 2022-5-20 09:56
yjqd 发表于 2022-5-20 09:53
谢谢,不好意思,麻烦了
关于字符集里字母的大小写也影响结果
test.txt:

没看出啥问题来,你要哪种结果呢?
作者: wuming520    时间: 2022-5-20 09:57
欢迎进群1067888280有答案
作者: yjqd    时间: 2022-5-20 10:15
szwp 发表于 2022-5-20 09:56
没看出啥问题来,你要哪种结果呢?

我不是否定你写的命令,我的意思是:比如我有时候没注意字符集里字母的大小写,会影响我只查找带中文字符的行的结果

即使就用这个命令,findstr /r /c:"[^ a-z0-9]",也把带Z的英文行查找出来了,而我只想查找有中文字符的行
test.txt:
Meng said the commission will step
one 129 ok
two78kl
three99 88 ui
thre99 88 ui6
中有粉因
bk高兴oewp
89爵士io
12听99
jkloppDZ



E:\win10pe10586制作\新建文件夹>findstr /r /c:"[^ a-z0-9]" test.txt
中有粉因
bk高兴oewp
89爵士io
12听99
jkloppDZ


谢谢!,麻烦了

作者: bjay2008xmy    时间: 2022-5-20 10:21
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-20 10:34
yjqd 发表于 2022-5-20 10:15
我不是否定你写的命令,我的意思是:比如我有时候没注意字符集里字母的大小写,会影响我只查找带中文字符 ...

这东西得你自己试的啊,你要忽略大小写在样本里提供也方便别人写啊,牙膏是挤不完的。

findstr /rc:"[^ a-z0-9A-Z]" text.txt
作者: nttwqz    时间: 2022-5-20 10:39
bjay2008xmy 发表于 2022-5-20 10:21
难道不是ascii码,-到'和!到Z吗

'前面为什么有空格?
作者: yjqd    时间: 2022-5-20 10:41
szwp 发表于 2022-5-20 10:34
这东西得你自己试的啊,你要忽略大小写在样本里提供也方便别人写啊,牙膏是挤不完的。

findstr /rc:"[ ...

非常感谢

我水平有限,不明其理只能胡乱测试,所以伸手向各位坛友求助
作者: szwp    时间: 2022-5-20 10:46
yjqd 发表于 2022-5-20 10:41
非常感谢

我水平有限,不明其理只能胡乱测试,所以伸手向各位坛友求助

findstr /ric:"[^ a-z0-9]" text.txt
findstr /ric:"[^ A-z0-9]" text.txt
findstr /ric:"[^ a-Z0-9]" text.txt
findstr /ric:"[^ A-Z0-9]" text.txt
正则写法不是唯一的,多试好为,复制粘贴可以少走弯路。
作者: szwp    时间: 2022-5-20 10:48
得学会 /?
findstr /?
/I         指定搜索不分大小写。
作者: bjay2008xmy    时间: 2022-5-20 11:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-20 11:51
nttwqz 发表于 2022-5-20 10:39
'前面为什么有空格?

样本里有不少空格啊。如果是8.3格式就不需要了。
作者: bjay2008xmy    时间: 2022-5-20 12:09
提示: 作者被禁止或删除 内容自动屏蔽
作者: bjay2008xmy    时间: 2022-5-20 12:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-20 13:00
bjay2008xmy 发表于 2022-5-20 12:50
^[%u4e00-%u9fa5]{0,}$这个正则表达式说是识别中文,咋没用呢

@echo off

中文是个比较复杂的事,国内第一代标准是GB2312-1980,含6千多个汉字,采用的是高位都为1的双字节方案。港台还有hz big5到gbk还没完,到后面还有四字节的中文。
他没说这个正则是什么编码的中文的话,你得去问问他适应范围。

作者: bjay2008xmy    时间: 2022-5-20 13:50
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-20 13:55
bjay2008xmy 发表于 2022-5-20 13:50
那有没有应用在此例中专门识别中文的正则表达式

中文数量显然远大于英文,用排除法省事。按3楼提示操作方便。
你要提供原始数据和结果数据以附件形式发上来试,因为已经变动过样本数据,不方便确定,他要大写还是小写了。


作者: bjay2008xmy    时间: 2022-5-20 13:59
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-20 14:11
bjay2008xmy 发表于 2022-5-20 13:59
没有通用的吗,我还以为有通用的不仅限于此例样本的正则表达式

findstr /rc:"[^'-Z]"

任何东西都离不了环境。
作者: 窄口牛    时间: 2022-5-20 19:54
能搞定吗?需要整理直播列表用。
作者: bjay2008xmy    时间: 2022-5-20 21:51
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-21 07:49
bjay2008xmy 发表于 2022-5-20 21:51
这确实是个好办法,解决问题的思路要比方法更重要

findstr "[^'-Z]"

findstr里字符的顺序不是标准的ascii,你可以搞个脚本将顺序搞出来比较。

以前叫纯中文,现在叫全角的,里面也包含数字英文符号制表符等,是否认为是中文得看你的需求,东西得靠自己调试。
作者: dos时代菜鸟    时间: 2022-5-21 10:08
还是要搞个 非中文的 字符集,做排除用。 比如英文的字符集


作者: nttwqz    时间: 2022-5-21 18:19
dos时代菜鸟 发表于 2022-5-21 10:08
还是要搞个 非中文的 字符集,做排除用。 比如英文的字符集

我曾经就有个奇葩的想法,把GBK中的所有中文相关字符都弄到一个记事本中用来匹配。。。
作者: 窄口牛    时间: 2022-5-21 18:42
简体转繁体就是吧,常用字对应。
作者: szwp    时间: 2022-5-21 20:45
dos时代菜鸟 发表于 2022-5-21 10:08
还是要搞个 非中文的 字符集,做排除用。 比如英文的字符集

也可试下非排除法,判断字符是否 >=啊 <=齄
作者: dos时代菜鸟    时间: 2022-5-21 22:05
本帖最后由 dos时代菜鸟 于 2022-5-21 22:26 编辑
szwp 发表于 2022-5-21 20:45
也可试下非排除法,判断字符是否 >=啊

这也是个思路

  1.     @echo off
  2.     setlocal ENABLEDELAYEDEXPANSION
  3.     set file1=test.txt
  4.     for /f "delims=" %%c in ('type !file1!') do (
  5.         call :str_x "%%c"
  6.         if !found0! EQU 1 ECHO [%%c]
  7.     )

  8.     pause
  9.     goto :eof

  10.     :str_x
  11.         set "str1=%~1"
  12.         SET found0=0
  13.         set n=0
  14.         :loop1
  15.         for %%i in (!n!) do (
  16.             set ch=!str1:~%%i,1!
  17.             if "!ch!"=="" exit /b
  18.             if not "!ch!"=="" (
  19.                 if "!ch!" GEQ "啊" ( if "!ch!" LEQ "齄" (
  20.                     set found0=1
  21.                     exit /b
  22.                 ))
  23.             )
  24.         )
  25.         set /a n +=1
  26.         goto loop1
  27.     exit /b
复制代码




作者: szwp    时间: 2022-5-22 09:46
dos时代菜鸟 发表于 2022-5-21 22:05
这也是个思路

当集合较大时,还是判断范围方便。这样可将16区前的全角符号制表符也排除了。
作者: nttwqz    时间: 2022-5-22 09:55
dos时代菜鸟 发表于 2022-5-21 22:05
这也是个思路

尽量少在for中使用call,遍历内容较少时没什么,多的时候很影响效率,你用for /l直接echo和call方式echo一试便知。
作者: 窄口牛    时间: 2022-5-22 10:02
英文没有一个占两个或者两个字节以上的哇,这是不是个突破点?
作者: dos时代菜鸟    时间: 2022-5-22 10:04
nttwqz 发表于 2022-5-22 09:55
尽量少在for中使用call,遍历内容较少时没什么,多的时候很影响效率,你用for /l直接echo和call方式echo ...

用call 主要用到 exit /b
如果 直接用 for ,就得用 goto
作者: szwp    时间: 2022-5-22 10:14
在中文全集中找太慢了吧
作者: bjay2008xmy    时间: 2022-5-22 10:49
提示: 作者被禁止或删除 内容自动屏蔽
作者: nttwqz    时间: 2022-5-22 11:50
dos时代菜鸟 发表于 2022-5-22 10:04
用call 主要用到 exit /b
如果 直接用 for ,就得用 goto

那就用goto跳出for循环。
你觉得用了call貌似觉得提高了效率,很可能效率反而更低。实际使用中,谁也不可能每次都测试不同写法的执行效率,所以还是少用为好。而且,你这也没到了需要权衡利弊到底用不用call的时候,完全可以不用。

1000时,不用call用时60毫秒,用call用时2120毫秒,是不用call的35倍。
  1. 10:59:54.53
  2. 10:59:54.59
  3. 10:59:56.71
  4. 请按任意键继续. . .
复制代码

  1. @echo off

  2. echo;%time%
  3. for /l %%a in (1 1 1000) do (
  4.     echo;%%a
  5. )>nul
  6. echo;%time%
  7. for /l %%a in (1 1 1000) do (
  8.     call :echoecho %%a
  9. )>nul
  10. echo;%time%
  11. pause

  12. exit

  13. :echoecho
  14.     echo;%~1
  15. goto :eof
复制代码






作者: nttwqz    时间: 2022-5-22 13:22
还是我以前想的方法简单

pushd %~dp0
findstr /i /g:GBK汉字.txt a.txt

GBK汉字.txt从网上搜集并整理,2万+汉字,删除了部分变成英文?并且英文?能匹配的“汉字”,有精力和条件的或者需要结果特别严禁精确的可以进一步整理,不过个人感觉,一般用途足够了,毕竟常用汉字才几千个。


GBK汉字.txt下载
GBK汉字_findstr匹配适用_GBK.7z (10.48 KB, 下载次数: 1)
作者: bjay2008xmy    时间: 2022-5-22 14:15
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-22 14:47
bjay2008xmy 发表于 2022-5-22 10:49
找个对正则匹配完全支持的命令行程序

不可能有完全支持的,就像要将win98或更前的exe放到11里运行,东西在发展,没结束前,哪有完全。
微软自家不同产品里的正则互相也不完全兼容。各种正则的原理不一样,查找的方式也不一样。
作者: szwp    时间: 2022-5-22 14:48
正则史比WIN史长。
作者: szwp    时间: 2022-5-22 15:28
nttwqz 发表于 2022-5-22 13:22
还是我以前想的方法简单

pushd %~dp0

只考虑常用汉字的话,gb2312够了。
主要看实际样本范围有多大。
作者: bjay2008xmy    时间: 2022-5-22 20:40
提示: 作者被禁止或删除 内容自动屏蔽
作者: dos时代菜鸟    时间: 2022-5-22 21:47
nttwqz 发表于 2022-5-22 11:50
那就用goto跳出for循环。
你觉得用了call貌似觉得提高了效率,很可能效率反而更低。实际使用中,谁也不 ...

确实如此,因为 call 本身就是一个耗时的指令,他相当于 变相调用 了一次 cmd 。
我用 call 并不是因为效率,只是  书写上的习惯,习惯 模块化 函数化 了。容易 模块化的 修改和 理解。

当然,对于这样单一目的的,确实没必要 搞一个函数来调用。


作者: szwp    时间: 2022-5-23 08:03
bjay2008xmy 发表于 2022-5-22 20:40
你这种方法应该是把样本和TXT里面的汉子逐一对比吧,看符不符合TXT里面的。如果样本有200个字符的话,不 ...

这个计算是错误的。学习正则重要的是自己尝试,别人常用的,是他们的环境。findstr需要/R选项才能使用正则表达式,这种说法是错误的,东西要靠自己尝试结果,转发未经核实的太浪费屏幕空间,也会误导。
你还需要补充中文的编码知识,\u4e00 明显不是GB码。GB2312的中文范围俺已经在47楼说了,仔细往下看贴。

初学者能掌握findstr的正则就能满足常用需求了,findstr /?里有 [x-y]    范围: 在指定范围内的任何字符
本题实际是一个xy的求解。上面发的findstr "[^'-Z]" ,你试了没有,这就是没有/R的正则表达式。
作者: bjay2008xmy    时间: 2022-5-23 11:24
提示: 作者被禁止或删除 内容自动屏蔽
作者: szwp    时间: 2022-5-24 08:18
bjay2008xmy 发表于 2022-5-23 11:24
%u4e00是UTF-8编码,如果用这个编码判断的话,样本的编码也应该要使用UTF-8编码

等你发示例教程教大家。




欢迎光临 无忧启动论坛 (http://bbs.wuyou.net/) Powered by Discuz! X3.3