含awk/read的Bash脚本在另一设备无法运行的排查求助
Bash脚本awk提取HTML内容在目标设备失效的解决办法
问题背景
本地运行的Bash脚本可从search HTML文件中提取带movieTitleCat类的a标签内的href路径,拼接基础URL后正常输出;但在搭载GNU bash 4.4.0(aarch64-unknown-linux-gnu)的设备上运行时,仅输出基础URL,无法提取href后的路径部分。
相关代码与示例
HTML片段:
<a class="movieTitleCat" tytul="Godzilla: Król potworów" id="14220" href="napisy-14220-Godzilla-Król-potworów-(1954)"><h3>Godzilla: Król potworów (Gojira) - 1954r. </h3></a>
原Bash脚本:
#!/bin/bash read -r -d "" awkCode << 'SEARCHTITLEAWKEOF' /movieTitleCat/ { match($0, /href="([^"]*)"/, cHref) printf("%s\n", (napiBase "/" cHref[1])) } SEARCHTITLEAWKEOF cat /home/gato/search | awk -v napiBase="http://lalalala.com" "$awkCode"
本地正常输出:
http://lalalala.com/napisy-14220-Godzilla-Król-potworów-(1954) http://lalalala.com/napisy-6336-Godzilla-(1984) ...
目标设备异常输出:
http://lalalala.com/ http://lalalala.com/ ...
问题诊断
核心原因是目标设备的awk版本不支持match()函数的第三个数组参数:
- GNU awk 4.0及以上版本才引入
match(string, regexp, array)语法,可将正则捕获组的内容存入指定数组; - 若目标设备的awk版本低于4.0,
cHref数组不会被赋值,cHref[1]为空字符串,最终只输出napiBase/。
可在目标设备执行以下命令验证awk版本:
awk --version
解决方案
方案1:使用POSIX兼容的awk语法(适配所有awk版本)
替换原脚本中的awk逻辑,用match()的内置变量RSTART和RLENGTH提取路径:
#!/bin/bash read -r -d "" awkCode << 'SEARCHTITLEAWKEOF' /movieTitleCat/ { line = $0 # 匹配href="xxx"格式的字符串 if (match(line, /href="[^"]*"/)) { # 截取掉href="和最后的",得到路径部分 href_path = substr(line, RSTART + 6, RLENGTH - 7) printf("%s/%s\n", napiBase, href_path) } } SEARCHTITLEAWKEOF cat /home/gato/search | awk -v napiBase="http://lalalala.com" "$awkCode"
RSTART:匹配字符串的起始索引;RLENGTH:匹配字符串的长度;substr(line, RSTART+6, RLENGTH-7):跳过href="(6个字符),减去末尾的"(1个字符),最终得到纯路径。
方案2:升级目标设备的GNU awk版本
如果目标设备允许软件升级,可将GNU awk升级到4.0及以上版本,原脚本即可直接正常运行。
内容的提问来源于stack exchange,提问作者D S
相关产品推荐
相关产品推荐

