Board logo

标题: 文本的模式匹配问题(搜索特定的单词) [打印本页]

作者: willsort     时间: 2005-9-10 00:26    标题: 文本的模式匹配问题(搜索特定的单词)

To All:

      现有一纯文本的字典文件,每一行都是由一英文单词和一个空格以及其汉语译词组成,按单词字母排序。有以下几个题目:

      1、从中找出所有的由abcde五个字母组成的单词所在行;
      2、从中找出所有的正向与反向拼读相同的单词所在行;
      3、从中找出所有的正向拼读与反向拼读均为字典中单词的单词对;

      不知有什么好的办法可以完成?
作者: JonePeng     时间: 2005-9-10 22:02
第一题好像没什么难度哦,用find命令就可以找到。
第二题和第三题是C、Pascal 编程的经典题目,用批处理很难办啊。
作者: willsort     时间: 2005-9-11 00:56
Re JonePeng:

      兄误会了,这并非批处理的题目,大家可以用任何方式来实现它,不论是已有软件,还是自主编程;无论是Windows环境,还是DOS平台。关键是要找出一个更为丰富的文本匹配模式,因为类似的问题还有很多,现在文本处理软件中的搜索不是简单的直接匹配,就是正则表达式,似乎无法描述主楼提到的各种问题。

      至于第一题用 find 实现,我很难理解,兄可以解释得更深入一些吗?

      另外,现想到一个与第一题相关的第四题,如下:

      4、从中找出所有的字母的组合相同而排列不同的单词(如not/ton);
作者: 无奈何     时间: 2005-9-26 22:22
这么有意思的题目为什么没人做呢?
无知者无畏,我来闯闯关。不知道有没有奖品?
先闯前两关吧!
我接触命令行时间不长,有错误请指教。

SearchString.bat
CODE:  [Copy to clipboard]
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: SearchString.bat - 从文本首列中找出所有的由特定字母组成的单词所在行
:: by: 无奈何 - 2005-9-26 - 联系:wunaihe@gmail.com
:: 用法:SearchString test.txt
:: 说明: - 测试环境WinXP。将“test.txt”替换为实际处理文本,可将
::       “set str=abcde”中abcde 替换为其它欲测字母。
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

@echo off
del log.txt 2>nul
setlocal ENABLEDELAYEDEXPANSION

:: 获取首列单词并提交string函数处理
for /f "tokens=1" %%i in (%1) do (
call :string %%i>>log.txt
)
:: 从原文件中确定匹配单词所在行
for /f "delims=" %%i in (log.txt) do (
findstr /n /r "\<%%i\>" %1
)
endlocal
goto :EOF

:: 判断单词只有特定字母组成后输出
@echo off
:string
setlocal ENABLEDELAYEDEXPANSION
set m=0
set n=0
set str=abcde
set str2=%1
:loop
if not defined str2 echo %1&endlocal &goto :EOF
if not defined m endlocal &goto :EOF
call set m=%%str:~%n%,1%%
set str2=!!str2:%m%=!!
set /a n+=1
goto loop
goto :EOF
测试文本
test.txt
CODE:  [Copy to clipboard]
abc 中国DOS联盟
ABC 中国DOS联盟
asdfdsa 中国DOS联盟
ghkll 中国DOS联盟
ABdba 中国DOS联盟
qwwq 中国DOS联盟
ABCDE 中国DOS联盟
woniu 中国DOS联盟
hgdfh 中国DOS联盟
ABBCCBBAA 中国DOS联盟
wunaihe 中国DOS联盟
fghg 中国DOS联盟
qwerewq 中国DOS联盟
aaaaaaaaaa 中国DOS联盟
aa 中国DOS联盟
a 中国DOS联盟

作者: 无奈何     时间: 2005-9-26 22:48
再来第二个。
好像正反拼读相同的字符叫回环字符来着吧?
英文太滥不知道怎么称呼,搜了个单词 loopback 不知对不?
测试文本可以用楼上的 test.txt。

loopback.bat
CODE:  [Copy to clipboard]
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: loopback.bat - 从文本首列中查找回环单词(正反拼读相同)所在行
:: by: 无奈何 - 2005-9-26 - 联系:wunaihe@gmail.com
:: 用法:loopback test.txt
:: 说明: - 测试环境WinXP。将“test.txt”替换为实际处理文本。
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

@echo off
del log.txt 2>nul
setlocal ENABLEDELAYEDEXPANSION

:: 获取首列单词并提交string函数处理
for /f "tokens=1" %%i in (%1) do (
call :string %%i>>log.txt
)
:: 从原文件中确定匹配单词所在行
for /f "delims=" %%i in (log.txt) do (
findstr /n /r "\<%%i\>" %1
)
endlocal
goto :EOF


:: 判断单词为回环字符后输出
:string
@echo off
setlocal ENABLEDELAYEDEXPANSION
set m=0
set n=0
set str=%1
set str2=
:loop
if not defined m (
        if /i "%str%" == "%str2%" (
                        echo %str%&endlocal &goto :EOF
                        ) else endlocal &goto :EOF
                         )

call set m=%%str:~%n%,1%%
set /a n+=1
set str2=!m!!str2!
goto loop
goto :EOF

作者: willsort     时间: 2005-9-26 22:56
Re 无奈何:

      感谢兄的积极参与!你的代码确有诸多亮点。但是你可能理解错了我的第一题的本意,我是指找出所有仅由abcde五个字母组成的单词,而且这5个字母在单词中必须出现且仅出现1次。

      不过,即便如此,相信将代码修改修改,也能完成此项任务,但是我的目标是实现能解上面4个问题的通用方案,所以我才提到需要建立一个新的文本匹配模式。当然,我并不反对兄单独求解以上题目,甚至十分欢迎;而如果能更进一步,自然是锦上添花了。
作者: 无奈何     时间: 2005-9-26 23:31
to willsort

不理解你的“通用方案”是什么意思?
NT 批处理的字符处理能力很弱,并且还有一些如 ! ^ & * 这样的字符夹杂的情况可能会出错。但可以完成简单的任务如 字符替换、获取字符串的单个或每个字符等。NT 批处理中字符处理能完成的最复杂的情况无非就是获取每个字符然后组合匹配。其它的再需要一点思路,然后祈祷能执行通过。

我也只是最近才对此感兴趣的,不知道理解的对不对?
作者: willsort     时间: 2005-9-27 17:29
Re 无奈何:

      我说的“通用方案”就是指可以用一种一以化之的模式描述我所提到的问题,正如正则表达式可以描述关于串中字符的形式和数量信息一样,因为正则表达式关于串中字符的排列顺序以及空间关系的描述过于薄弱了(就只有^和$),所以我才提出需要建立一种新模式,可以描述这种排列顺序和空间关系,以解决此一系列的问题。我并没有说,这种模式一定要借助批处理或命令行程序来建立,我们可以采取各种可能的办法。

      至于NT的字符串处理能力,与Win9x/MSDOS相比,已好得很多了,至少处理普通的字典文件没有什么大问题。
作者: 220110     时间: 2005-9-27 21:53
“一以化之的模式 ”,那这程序的算法。。。。恐怖,
假如我可以写得出得话,电脑一定死给我看,呵呵呵,,
作者: 无奈何     时间: 2005-9-27 23:36
to willsort
我也很希望能见到如你所说更好的理想化的描述字符的匹配模式。好像现在最实际的就是正则表达式了。
再者正则表达式并不只是“只有^和$”,还有其它字符定位符如:
\b 匹配一个单词边界
\B 匹配非单词边界
(?=pattern) 正向预查,分组中的模式必须出现在声明的右侧
(?!pattern) 负向预查,分组中的模式不得出现在声明的右侧
只是常见的正则表达式查询和编辑软件不支持罢了,我对此并不深懂,详情你可以查询一下Perl正则全集。




欢迎光临 中国DOS联盟论坛 (http://cndos.fam.cx/forum/) Powered by Discuz! 2.5