我的桌面上有一个很大的 html 文件,看起来像
src="http://images.alaablubnan.com/images/Balls/20.jpg"
alt="http://images.alaablubnan.com/images/Balls/20.jpg"/></a></td><td><a
href="http://images.alaablubnan.com/images/Balls/32.jpg"
target="_blank"><img
src="http://images.alaablubnan.com/images/Balls/32.jpg"
alt="http://images.alaablubnan.com/images/Balls/32.jpg"/></a></td><td><a
href="http://images.alaablubnan.com/images/Balls/30.jpg"
target="_blank"><img
src="http://images.alaablubnan.com/images/Balls/30.jpg"
alt="http://images.alaablubnan.com/images/Balls/30.jpg"/></a></td></tr><tr><td><table><tr><td>webpage/url</td><td>http://www.playlebanon.com/webservices/website/lotto/PopUps/HistoryDetail.aspx?t=1405536730503&FromDraw=1&ToDraw=1213&Draw=0</td></tr></table></td><td>2</td><td>complete
lotto results</td><td>complete lotto results</td><td>2</td><td><a
href="http://www.playlebanon.com/webservices/website/lotto/PopUps/HistoryDetail.
如果可能的话,我想:
- 获取所有 .jpg 文件,删除所有 html 代码(包括 1.jpg、2.jpg... 到 42.jpg)
- 我想删除 .jpg 扩展名
- 我希望每行数字只有 7 个数字,然后插入新行
答案1
这实际上并不是一份特别好的工作,sed
但情况如下:
sed -nr 's#.*/([^"]+).jpg.*#\1#p' file
以上将为您提供一个数字列表,每行一个:
20
20
32
32
32
30
30
30
现在,实际上可以将所有这些放在同一行,每行 7 个数字,sed
但这真的不值得付出努力。只需使用标准 *nix 工具即可:
$ echo $(sed -nr 's#.*/([^"]+).jpg.*#\1#p' file | tr $'\n' ' ') | fold -sw 21
20 20 32 32 32 30 30
30
或者,如果您想删除重复项:
echo $(sed -nr 's#.*/([^"]+).jpg.*#\1#p' file | sort -u | tr $'\n' ' ')
20 30 32
解释
该sed
命令使用了一些技巧:
-n
:默认情况下不打印任何行。-r
:启用扩展正则表达式,这让我们可以( )
使用捕获组而不需要转义括号和+
“一个或多个”。s#from#to#
sed
: 虽然和其他类似工具中的标准替换运算符是s/from/to/
,但您可以使用非标准分隔符,以便将其包含/
在模式中。在本例中,我使用的是#
但您也可以使用其他类似的东西s|from|to|
。s#.*/([^"]+).jpg.*#\1#p
:这将匹配从行首到 a 的所有内容/
,然后捕获最长的非 字符,"
直到.jpg
。这是文件名减去扩展名。文件名在括号中捕获,整行(因为.*
两边都有 )将替换为捕获的模式(\1
)。p
末尾的 表示它将打印替换成功的行。
perl
但就我个人而言,我首先会这样做:
$ perl -e '@k=grep(s/.*\/([^"]+).jpg.*/$1/s,<>); print "@k[0..6]\n@k[7..$#k]\n"' file
20 20 32 32 32 30 30
30
或者,对于较大的文件:
$ perl -e '@k=grep(s/.*\/([^"]+).jpg.*/$1/s,<>); for($i=0;$i<=$#k;$i+=7){print "@k[$i..$i+7]\n"}' file
20 20 32 32 32 30 30 30
30
甚至grep
:
$ echo $(grep -oP '[^/]+(?=.jpg)' file | tr $'\n' ' ' ) | fold -w 21
20 20 32 32 32 30 30
30
或者,窃取@Olli 的聪明xargs
想法:
$ grep -oP '[^/]+(?=.jpg)' file | xargs -n7 echo
20 20 32 32 32 30 30
30
答案2
我假设您试图抓取某种结果。在这个例子中,只有三个球,我们可以通过搜索Balls/<one-or-many-digits>
并围绕数字分组(构造\(..\)
)然后用该组替换所有球(是\1
对第一个组的引用)来提取它们。
$ sed -n 's/.*Balls\/\([0-9]\+\).*/\1/gp' htmlfile | uniq | xargs -n7 echo
20 32 30
sed
逐行检查。我要求它匹配并替换行上的所有内容(这就是为什么我们在每个末尾都加上.*
“任意数量”的原因),将其替换为组中匹配的内容。 和-n
一起/p
使用表示除非该行匹配,否则不打印, 表示/g
它会一直匹配,直到到达文件末尾。
如果您不熟悉正则表达式,这是一个相当复杂的例子。
我将其传递过去,uniq
因为那里有很多重复。
我| xargs -n7 echo
在末尾使用将 7 个参数组合在一起并将它们全部传递给echo
。这里没有 7 个球,所以只显示 3 个。
-r
它可能会减慢速度,但如果使用扩展语法,则可以获得更易读的表达式sed
:
sed -nr 's/.*Balls\/([0-9]+).*/\1/gp' htmlfile | ...
做同样的事情,只是没有一些看起来令人困惑的转义。
可能稍微慢一点。