标题: [文本处理] [已解决]如何使用 gawk.exe 获取html文件中的字符串? [打印本页]
作者: hnfeng 时间: 2024-7-7 21:34 标题: [已解决]如何使用 gawk.exe 获取html文件中的字符串?
本帖最后由 hnfeng 于 2024-7-9 08:12 编辑
下面代码是 html 文件的一部分- <一些无关字符>
- <table width="100%" border="1" cellpadding="5" cellspacing="0" bordercolor="#E3F2FD">
- <tr bgcolor="#1565C0"><td colspan="4"><strong><font color="#FFFFFF" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">日志报告:概述</font></strong>
- </td></tr>
- <tr>
- <td bgcolor="#BBDEFB"><strong><font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">任务名称</font></strong></td>
- <td width="23%" bgcolor="#FFFFFF"><font size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">2.5_activity_H2J</font></td>
- <td bgcolor="#BBDEFB"><font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"><strong>类别</strong></font></td>
- <一些无关字符>
- </tr>
- <tr>
- <td bgcolor="#BBDEFB"><strong><font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">开始检查</font></strong></td>
- <td width="23%" bgcolor="#FFFFFF"><font size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">2024-07-05 23:14:49</font></td>
- <td bgcolor="#BBDEFB"><font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"><strong>检查完毕</strong></font></td>
- <td width="39%" bgcolor="#FFFFFF"><font size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">2024-07-06 02:34:51 (3 小时, 20 分钟, 2 秒)</font></td>
- </tr>
- <tr>
- <td bgcolor="#BBDEFB"><strong><font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">同步任务开始时间</font></strong></td>
- <td width="23%" bgcolor="#FFFFFF"><font size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">2024-07-05 21:06:08</font></td>
- <td bgcolor="#BBDEFB"><font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"><strong>同步任务结束时间</strong></font></td>
- <td width="39%" bgcolor="#FFFFFF"><font size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif">2024-07-06 02:44:46 (5 小时, 38 分钟, 37 秒)</font></td>
- </tr>
- </table>
- <一些无关字符>
复制代码
想获取里面的信息:
2.5_activity_H2J
2024-07-05 21:06:08
2024-07-05 23:14:49
2024-07-06 02:34:51
2024-07-06 02:44:46
请教怎样使用 gawk.exe (其他批处理、第三方也可以)获取上面的字符串,存到一个文本文件中。
多谢了
作者: aloha20200628 时间: 2024-7-7 22:28
本帖最后由 aloha20200628 于 2024-7-8 08:41 编辑
回复 1# hnfeng
若需更完整的匹配,代码第2行可改为 ‘日期+时间’ 两个字段的正则式》
"[0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]"
- @echo off & (for /f "tokens=3 delims=<>(" %%a in (
- 'findstr /ic:"_activity_" /rc:"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]" 1.html') do echo,%%a)>1.tmp
- sort 1.tmp>1.txt
- del "1.tmp"&pause&exit/b
复制代码
作者: hnfeng 时间: 2024-7-8 07:29
本帖最后由 hnfeng 于 2024-7-8 07:34 编辑
回复 2# aloha20200628
哦,不好意思,我没有说清楚,我的意思是 按顺序 获取 任务名称 和 各个时间:
任务名称
2.5_activity_H2J
同步任务开始时间
2024-07-05 21:06:08
开始检查
2024-07-05 23:14:49
检查完毕
2024-07-06 02:34:51
同步任务结束时间
2024-07-06 02:44:46
但是输出结果只要任务名称和各个时间
作者: aloha20200628 时间: 2024-7-8 08:42
回复 3# hnfeng
2楼代码已订正,加个排序就可以了
作者: aloha20200628 时间: 2024-7-8 09:39
回复 3# hnfeng
不用临时文件的版本...
- @echo off & (for /f "tokens=3 delims=<>(" %%a in (
- 'findstr /ic:"_activity_" /rc:"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]" 1.html') do @echo,%%a)|sort>1.txt
- pause&exit/b
复制代码
作者: hnfeng 时间: 2024-7-8 11:10
回复 hnfeng
不用临时文件的版本...
aloha20200628 发表于 2024-7-8 09:39
谢谢帮忙,这个 sort 很巧妙
不过,html 文件中的 任务名称 可能是其他的 不含 _activity 的字符串,貌似也没明显的共有字符串可 findstr,所以能否再改改,通用一点(html格式是一样的)
主要是 任务名称 不同。就是找到文字 任务名称 ,然后取下一行的 非代码字符的文字
作者: aloha20200628 时间: 2024-7-8 12:59
本帖最后由 aloha20200628 于 2024-7-8 13:39 编辑
回复 6# hnfeng
因为要先提取 ‘任务名称’ 这个中文字段,故须确认1.html的编码,以下代码假设其为系统默认编码(936 即 gb2312);
若1.html是utf-8编码,则须抹去代码第2行首的::注释前缀,还须将代码脚本存为utf-8编码后运行...
- @echo off &set "hF=1.html"
- ::chcp 65001>nul & @echo off
- for /f "tokens=1 delims=:" %%n in (' findstr /lnc:">任务名称<" "%hF%" ') do set/a "n=%%n+1"
- (for /f "tokens=4 delims=<>" %%a in (' findstr /n ".*" "%hF%"^|findstr /lbc:"%n%:" ') do echo,%%a)>1.txt
- (for /f "tokens=3 delims=<>(" %%a in (
- ' findstr /rc:"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]" "%hF%" ') do @echo,%%a)|sort>>1.txt
- pause&exit/b
复制代码
作者: Five66 时间: 2024-7-8 13:07
不知行否
注意html的编码- gawk "$0 ~ /任务名称|开始检查|检查完毕|同步任务..时间/{(getline);a=$0;gsub(/<[^>]*>/,\"\",a);print a}" 1.html >1.txt
复制代码
作者: hnfeng 时间: 2024-7-8 13:26
回复 hnfeng
因为要先提取 ‘任务名称’ 这个中文字段,故须确认1.html的编码,以下代码假设其为系统默 ...
aloha20200628 发表于 2024-7-8 12:59
不成功,编码是 UTF-8,已经按你说的第二行删掉前面的两个冒号,以及保存批处理文件为 UTF-8 (是否有 BOM 都试了)
作者: hnfeng 时间: 2024-7-8 13:27
不知行否
注意html的编码
Five66 发表于 2024-7-8 13:07
不成功,编码是 UTF-8
作者: aloha20200628 时间: 2024-7-8 13:48
回复 9# hnfeng
在7楼代码中3-4行之间加入 echo,%n% 检查获取目标行号是否正确?
再粘贴看看生成的 1.txt 究竟啥样?
作者: 77七 时间: 2024-7-8 14:01
本帖最后由 77七 于 2024-7-8 14:57 编辑
楼主文件为utf-8,以下代码保存为utf-8。- @echo off
- chcp 65001 >nul
- cd /d "%~dp0"
- set str="任务名称" "同步任务开始时间" "开始检查" "检查完毕" "同步任务结束时间"
- for %%a in (%str%) do (
- set _"%%~a"=1
- )
- setlocal enabledelayedexpansion
- for /f "useback tokens=3,4 delims=<>(" %%a in ("1.xml") do (
- if defined _"%%b" (
- set b=%%b
- ) else if defined b (
- call set "str=%%str:"!b!"="!b!" "%%a"%%"
- set b=
- )
- for %%a in (!str!) do (
- set /a n+=1
- )
- if !n! equ 10 (
- for %%a in (!str!) do (
- echo %%~a
- endlocal
- setlocal enabledelayedexpansion
- )
- )
- set n=
- )
- endlocal
- pause
复制代码
部分命令顺序写错了,不过不影响结果。第22-23行可写到原24行下,这样逻辑清晰点。
作者: 77七 时间: 2024-7-8 14:08
回复 12# 77七
一些多余了
21行改为- if not defined _"%%~a" echo %%~a
复制代码
作者: hnfeng 时间: 2024-7-8 14:16
回复 77七
一些多余了
21行改为
77七 发表于 2024-7-8 14:08
成功成功,多谢了
作者: hnfeng 时间: 2024-7-8 14:18
回复 11# aloha20200628 - 10.0.19045)
- 10.0.19045)
- 2024-07-05 21:06:08
- 2024-07-05 23:14:49
- 2024-07-06 02:34:51
- 2024-07-06 02:44:46
- FastMM.Normal)
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- font color="#000077" size="3" face="Segoe UI Variable, Segoe UI, Verdana, sans-serif"
- TM) i5~13400
- x86)
- x86)\AOMEI\AOMEI Backupper\7.3.2;
- x86)\Common Files
- xxxxxxxxxxxx)
- 成功)
- 成功)
- 成功)
- 成功)
- 成功)
- 成功)
- 成功)
复制代码
作者: aloha20200628 时间: 2024-7-8 15:00
本帖最后由 aloha20200628 于 2024-7-8 15:03 编辑
回复 15# hnfeng
一。楼主自己判断用7楼代码获取的“任务名称”所在的行号正确吗?正确值应该是 %n%-1
二。15楼对应的源文件还是utf-8编码的一楼示例文件吗?
如果不是,能否如一楼示例样本那样粘贴出来看看,以便测试检查其中的字段位序有否变化...因为我用7楼代码已对utf-8编码的一楼样本测试通过了
借此也可判断究竟是findstr的性能或用法还是其他问题...
作者: hnfeng 时间: 2024-7-8 16:07
回复 16# aloha20200628
貌似 没有获取到行号 n
echo %n% 显示 ECHO is off.
1楼的代码是精简了的,<一些无关字符> 省略掉了,不然太长
作者: qixiaobin0715 时间: 2024-7-8 16:33
本帖最后由 qixiaobin0715 于 2024-7-8 17:01 编辑
批处理文件保存格式如12楼:- @echo off
- chcp 65001>nul
- setlocal enabledelayedexpansion
- for %%i in (任务名称 同步任务开始时间 开始检查 检查完毕 同步任务结束时间) do (
- set /a n+=1
- set /a _%%i=n
- )
- for /f "tokens=3,4 delims=><(" %%i in (1.html) do (
- if defined _!str! (
- set /a m=_!str!
- set #!m!=%%i
- if !m! equ 5 (
- for /l %%k in (1,1,5) do echo,!#%%k!
- )
- )
- set str=%%j
- )
- pause
复制代码
作者: WHY 时间: 2024-7-8 16:53
本帖最后由 WHY 于 2024-7-8 16:55 编辑
批处理编码为 UTF-8 Without BOM- @echo off
- set "reg=^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}"
- gawk -b "{if(match($0, />([^<>]+)<\//, a) && match(a[1], /%reg%/, b))c[++i]=b[0]; else if(s==\"任务名称\")s0=a[1]; s=a[1]} END {asort(c); print s0; for(i in c)print c[i]}" 1.html > 1.txt
- pause
复制代码
作者: aloha20200628 时间: 2024-7-8 16:57
本帖最后由 aloha20200628 于 2024-7-8 17:06 编辑
回复 17# hnfeng
看来还是要敲打一下 findstr 对utf-8编码文件中的中文数据匹配能力
改用 find 匹配中文数据要比 findstr 强悍,但其代价是没有了正则功能,好在本帖要求的仅是匹配一个中文字面量 ‘任务名称’ 而已 ...
楼主再用以下代码试试,应该可以了...也是对批处采用 findstr/find 的权衡与分寸提供一个第一手的实例
- @echo off &chcp 65001>nul &@echo off &set "hF=1.html"
- for /f "tokens=1 delims=[]" %%n in ('find /n ">任务名称<" "%hF%"^|more +2') do set/a "n=%%n+1"
- (for /f "tokens=4 delims=<>" %%a in (' findstr /n ".*" "%hF%"^|findstr /lbc:"%n%:" ') do echo,%%a)>1.txt
- (for /f "tokens=3 delims=<>(" %%a in (
- ' findstr /rc:"[0-9][0-9]:[0-9][0-9]:[0-9][0-9]" "%hF%" ') do @echo,%%a)|sort>>1.txt
- pause&exit/b
复制代码
作者: WHY 时间: 2024-7-8 16:59
本帖最后由 WHY 于 2024-7-8 17:06 编辑
批处理编码为 ANSI- <# :
- @echo off
- PowerShell ". ([ScriptBlock]::Create((gc -Literal '%~f0') -join \"`r`n\")) '1.html'"
- pause & exit
- #>
-
- $Hash = @{任务名称=0; 同步任务开始时间=1; 开始检查=2; 检查完毕=3; 同步任务结束时间=4};
- $out = @('', '', '', '', '');
- $str = [IO.File]::ReadAllText($args[0], [Text.Encoding]::UTF8);
-
- forEach ($m In [regex]::Matches($str, '>([^<>]+)</')) {
- If ($s -ne $null -and $Hash.ContainsKey($s)) {
- $n = $Hash[$s];
- $out[$n] = $m.Groups[1].Value;
- }
- $s = $m.Groups[1].Value;
- }
-
- $out -replace '\(.*$';
复制代码
作者: Five66 时间: 2024-7-8 20:06
回复 10# hnfeng - gawk "$0 ~ /\xE4\xBB\xBB\xE5\x8A\xA1\xE5\x90\x8D\xE7\xA7\xB0|\xE5\xBC\x80\xE5\xA7\x8B\xE6\xA3\x80\xE6\x9F\xA5|\xE6\xA3\x80\xE6\x9F\xA5\xE5\xAE\x8C\xE6\xAF\x95|\xE5\x90\x8C\xE6\xAD\xA5\xE4\xBB\xBB\xE5\x8A\xA1..\xE6\x97\xB6\xE9\x97\xB4/{(getline);a=$0;gsub(/<[^>]*>/,\"\",a);print a}" 1.html >1.txt
复制代码
作者: newswan 时间: 2024-7-8 22:17
回复 1# hnfeng
最好发文件,方便测试
作者: hnfeng 时间: 2024-7-9 08:04
批处理文件保存格式如12楼:
qixiaobin0715 发表于 2024-7-8 16:33
成功成功,多谢多谢
作者: hnfeng 时间: 2024-7-9 08:10
批处理编码为 ANSI
WHY 发表于 2024-7-8 16:59
成功成功,多谢多谢了
作者: hnfeng 时间: 2024-7-9 08:11
谢谢以上各位的帮忙
作者: hnfeng 时间: 2024-7-9 08:11
谢谢以上各位的帮忙
作者: qixiaobin0715 时间: 2024-7-9 08:20
回复 18# qixiaobin0715
代码12、13行的数字5可改为!n!,这样更通用一些。
作者: aloha20200628 时间: 2024-7-9 09:28
本帖最后由 aloha20200628 于 2024-7-9 19:56 编辑
回复 27# hnfeng
如果改用 find.exe 匹配utf-8网页中的汉字数据无误,可用以下代码一气呵成,无须用批处逐行遍历整个网页,也免去sort排序...
- @echo off &chcp 65001>nul&@echo off &del/q 1.txt 2>nul &set "hF=1.html"
- set "kws=任务名称,同步任务开始时间,开始检查,检查完毕,同步任务结束时间"
- :[loop]
- for /f "tokens=1* delims=," %%a in ("%kws%") do set "kw=%%a"&set "kws=%%b"
- for /f "tokens=1 delims=[]" %%n in ('find /n ">%kw%<" "%hF%"^|more +2') do set/a "n=%%n+1"
- (for /f "tokens=4 delims=<>(" %%a in (' findstr /n ".*" "%hF%"^|findstr /lbc:"%n%:" ') do echo,%%a)>>1.txt
- if "%kws%"=="" (pause&exit/b) else goto[loop]
复制代码
作者: hnfeng 时间: 2024-7-9 10:07
回复 qixiaobin0715
代码12、13行的数字5可改为!n!,这样更通用一些。
qixiaobin0715 发表于 2024-7-9 08:20
谢谢谢谢,已经更新
作者: hnfeng 时间: 2024-7-9 10:08
回复 hnfeng
如果改用 find.exe 匹配utf-8网页中的汉字数据无误,可用以下代码一气呵成...
aloha20200628 发表于 2024-7-9 09:28
谢谢谢谢
作者: qixiaobin0715 时间: 2024-7-9 15:33
本帖最后由 qixiaobin0715 于 2024-7-9 15:45 编辑
楼主未直接提供html文件,只是摘写了片段,不知实际内容如何。按照顶楼文件片段分析,如果要使用findstr命令,可提取行首带有“<td”标签的行,来过滤掉无用的内容,而不需要考虑的太复杂。像这样使用:复制代码
作者: hnfeng 时间: 2024-7-9 17:00
回复 32# qixiaobin0715
上面多位网友的代码都能实现,目前使用了18楼的代码(主要因为我能看懂)
我把一个html文件传到度盘吧,有想继续研究的请看看(7天有效期)- https://pan.baidu.com/s/1_tWWy4L-C8qftA0T3qwGGQ?pwd=1234
复制代码
作者: hnfeng 时间: 2024-7-9 17:02
回复 20# aloha20200628
文件发这里了- https://pan.baidu.com/s/1_tWWy4L-C8qftA0T3qwGGQ?pwd=1234
复制代码
作者: aloha20200628 时间: 2024-7-9 17:34
回复 34# hnfeng
将29楼代码存为utf-8编码脚本,用楼主最新提供的 ‘3_2.5_activity_H2J_Log_Page1.html’ (更名为代码中设定的 1.html)测试顺利通过
作者: hnfeng 时间: 2024-7-9 17:52
回复 hnfeng
将29楼代码存为utf-8编码脚本,用楼主最新提供的 ‘3_2.5_activity_H2J_Log_Page1.html’ ...
aloha20200628 发表于 2024-7-9 17:34
是的是的,上面多位朋友的代码都可以顺利通过
作者: newswan 时间: 2024-7-9 18:24
本帖最后由 newswan 于 2024-7-9 18:28 编辑
powershell- $file = ".\3_2.5_activity_H2J_Log_Page1.html"
-
- $Hash = [Ordered]@{ "任务名称" = "" ; "开始检查" = "" ; "检查完毕" = "" ; "同步任务开始时间" = "" ; "同步任务结束时间" = "" }
-
- $arr = (( Get-Content -Path $file -Encoding UTF8 -Raw ) -replace "<[^>]*>" -replace "`r" ) -split "`n"
-
- for ( $i=0 ; $i -lt $arr.Count ; $i++ ) {
- if ( $arr[$i] -in $hash.Keys ) {
- $hash[$arr[$i]] = $arr[$i+1]
- }
- }
-
- $Hash
复制代码
作者: aloha20200628 时间: 2024-7-9 19:47
本帖最后由 aloha20200628 于 2024-7-9 19:52 编辑
跟跑本帖至此,可对findstr/find匹配 ‘双字节数据如中文数据’ 的能力给一个小结,针对楼主所给网页测试文件的实测结果》
一。若网页文件是系统默认编码(936或gb2312或记事本ansi)
findstr 用 /c:"..." 或 /lc:"..." 或 /rc:"..." 或 /ic:"..." 参数均可成功匹配测试文件中的5个中文关键词
二。若网页文件是utf-8编码
findstr 用 /c:"..." 或 /lc:"..." 或 /rc:"..." 或 /ic:"..." 参数均未成功匹配测试文件中的5个中文关键词
改用 find 即可成功匹配测试文件中的5个中文关键词(备注:find不支持正则表达式)
三。无论文本文件是系统默认编码还是utf-8编码,cmd窗口采用936或65001码页均可正确显示 ‘其中的ascii字符’,故无须专门切换相应的码页,findstr 即可成功匹配 ‘文件中的ascii字符数据’...
作者: newswan 时间: 2024-7-9 20:35
跟跑本帖至此,可对findstr/find匹配 ‘双字节数据如中文数据’ 的能力给一个小结,针对楼主所给网页测试 ...
aloha20200628 发表于 2024-7-9 19:47
总之,放弃这些没有前途的,改 powershell
作者: WHY 时间: 2024-7-9 21:53
Test.bat,脚本保存为ANSI编码- @if(0)==(0) echo off
- cscript //nologo //e:jscript "%~f0" 1.html > 1.txt
- pause & exit
- @end
-
- var srcFile = WSH.Arguments(0);
- var obj = {任务名称:'', 同步任务开始时间:'', 开始检查:'', 检查完毕:'', 同步任务结束时间:''}
-
- var getText = function(file) {
- var ado = new ActiveXObject('ADODB.Stream');
- ado.Mode = 3;
- ado.Type = 2;
- ado.Charset = 'utf-8';
- ado.Open();
- ado.LoadFromFile(file);
- var str = ado.ReadText(-1);
- ado.Close();
- return str;
- }
-
- var html = new ActiveXObject('htmlfile');
- html.write(getText(srcFile));
- var node = html.getElementsByTagName('td')
-
- for(var i=0; i<node.length-1; i++){
- var s = node[i].innerText;
- if (obj.hasOwnProperty(s)) obj[s] = node[i+1].innerText.replace(/\(.*$/, '');
- }
-
- for (var k in obj) WSH.Echo(obj[k]);
复制代码
作者: WHY 时间: 2024-7-9 22:29
回复 39# newswan
个人观点:
你认为"有前途"的,其他人或许认为就是辣鸡。
不管啥方法,只要能解决实际问题,没有绝对好坏之分。
作者: hfxiang 时间: 2024-7-17 09:29
回复 1# hnfeng
用gawk的解决方法如下:
下载特定版本(mbcs,3.1.7) ( http://bcn.bathome.net/tool/mbcs,3.1.7/gawk.exe )
一、在命令行下执行:- gawk -W ctype=UTF8 "/(\344\273\273\345\212\241\345\220\215\347\247\260)|(\345\220\214\346\255\245\344\273\273\345\212\241\345\274\200\345\247\213\346\227\266\351\227\264)|(\345\274\200\345\247\213\346\243\200\346\237\245)|(\346\243\200\346\237\245\345\256\214\346\257\225)|(\345\220\214\346\255\245\344\273\273\345\212\241\347\273\223\346\235\237\346\227\266\351\227\264)/{A=1;next}A==1{A=0;print substr(gensub(/^<.+>([^<>]+)<.+>$/,\"\\1\",\"1\",$0),1,19)}" 3_2.5_activity_H2J_Log_Page1.html>out.txt
复制代码
二、将以下文本以utf-8编码保存为a.awk- /(任务名称)|(同步任务开始时间)|(开始检查)|(检查完毕)|(同步任务结束时间)/ {
- A = 1
- next
- }
- A == 1 {
- A = 0
- print substr(gensub(/^<.+>([^<>]+)<.+>$/, "\\1", "1", $0), 1, 19)
- }
复制代码
然后在命行下执行:gawk -W ctype=UTF8 -fa.awk 3_2.5_activity_H2J_Log_Page1.html>out.txt
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |