Lyn*_*nob 5 command-line text-processing
我的桌面上有一个很大的 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.
Run Code Online (Sandbox Code Playgroud)
如果可能,我想:
ter*_*don 11
这实际上并不是一个特别好的工作,sed但这里有:
sed -nr 's#.*/([^"]+).jpg.*#\1#p' file
Run Code Online (Sandbox Code Playgroud)
以上将为您提供一个数字列表,每行一个:
20
20
32
32
32
30
30
30
Run Code Online (Sandbox Code Playgroud)
现在,实际上可以使用每行 7 个数字将所有这些放在同一行上,sed但这确实不值得付出努力。只需使用标准的 *nix 工具:
$ echo $(sed -nr 's#.*/([^"]+).jpg.*#\1#p' file | tr $'\n' ' ') | fold -sw 21
20 20 32 32 32 30 30
30
Run Code Online (Sandbox Code Playgroud)
或者,如果您想删除重复项:
echo $(sed -nr 's#.*/([^"]+).jpg.*#\1#p' file | sort -u | tr $'\n' ' ')
20 30 32
Run Code Online (Sandbox Code Playgroud)
该sed命令使用了一些技巧:
-n: 默认情况下不打印任何行。-r: 启用扩展的正则表达式,这让我们可以( )用来捕获组而无需转义括号和+“一个或多个”。s#from#to#: 虽然标准替换运算符 insed和其他类似工具是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
Run Code Online (Sandbox Code Playgroud)
或者,对于更大的文件:
$ 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
Run Code Online (Sandbox Code Playgroud)
或grep甚至:
$ echo $(grep -oP '[^/]+(?=.jpg)' file | tr $'\n' ' ' ) | fold -w 21
20 20 32 32 32 30 30
30
Run Code Online (Sandbox Code Playgroud)
或者,窃取@Olli 的聪明xargs主意:
$ grep -oP '[^/]+(?=.jpg)' file | xargs -n7 echo
20 20 32 32 32 30 30
30
Run Code Online (Sandbox Code Playgroud)
我假设您正在尝试获取某种结果。在这个例子中只有三个球,我们可以通过围绕数字搜索Balls/<one-or-many-digits>和分组(\(..\)构造)然后用该组替换整个批次(这\1是对第一组的引用)来提取它们。
$ sed -n 's/.*Balls\/\([0-9]\+\).*/\1/gp' htmlfile | uniq | xargs -n7 echo
20 32 30
Run Code Online (Sandbox Code Playgroud)
sed正在逐行通过此行。我要求它匹配并替换该行上的所有内容(这就是为什么我们用.*“任何数量的任何东西”来限制每个结尾)与组中匹配的任何内容。在-n和/p一起使用,不打印,除非线是比赛和/g手段它会继续匹配,直到它遇到文件的末尾。
如果您不熟悉正则表达式,这是一个相当复杂的示例。
我正在通过它,uniq因为那里有很多重复。
我| xargs -n7 echo最后使用将 7 个参数组合在一起并将它们全部传递到echo. 这里没有 7 个球,所以它只显示了 3 个。
它可能会减慢它的速度,但如果您使用以下-r扩展语法,您可以获得稍微更具可读性的表达式sed:
sed -nr 's/.*Balls\/([0-9]+).*/\1/gp' htmlfile | ...
Run Code Online (Sandbox Code Playgroud)
做同样的事情,只是没有一些令人困惑的逃避。
可能会稍微慢一点。